diff --git a/apps/segmentrouting/BUILD b/apps/segmentrouting/BUILD
deleted file mode 100644
index 1304a5e..0000000
--- a/apps/segmentrouting/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-BUNDLES = [
-    "//apps/segmentrouting/app:onos-apps-segmentrouting-app",
-    "//apps/segmentrouting/web:onos-apps-segmentrouting-web",
-]
-
-onos_app(
-    category = "Traffic Steering",
-    description = "Segment routing application.",
-    included_bundles = BUNDLES,
-    required_apps = [
-        "org.onosproject.route-service",
-        "org.onosproject.mcast",
-        "org.onosproject.portloadbalancer",
-    ],
-    title = "Segment Routing",
-    url = "http://onosproject.org",
-)
diff --git a/apps/segmentrouting/app/BUILD b/apps/segmentrouting/app/BUILD
deleted file mode 100644
index c6844a6..0000000
--- a/apps/segmentrouting/app/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + CLI + [
-    "//core/common:onos-core-common",
-    "//core/store/serializers:onos-core-serializers",
-    "//apps/route-service/api:onos-apps-route-service-api",
-    "//apps/mcast/api:onos-apps-mcast-api",
-    "//apps/mcast/cli:onos-apps-mcast-cli",
-    "//apps/portloadbalancer:onos-apps-portloadbalancer",
-]
-
-TEST_DEPS = TEST_ADAPTERS + [
-    "//core/net:onos-core-net",
-    "//apps/route-service/api:onos-apps-route-service-api-tests",
-]
-
-osgi_jar_with_tests(
-    karaf_command_packages = ["org.onosproject.segmentrouting.cli"],
-    test_deps = TEST_DEPS,
-    deps = COMPILE_DEPS,
-)
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
deleted file mode 100644
index 38d8aac..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2016-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.ImmutableSet;
-import com.google.common.collect.Sets;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Handles Segment Routing app config events.
- */
-public class AppConfigHandler {
-    private static final Logger log = LoggerFactory.getLogger(AppConfigHandler.class);
-    private final SegmentRoutingManager srManager;
-    private final DeviceService deviceService;
-
-    /**
-     * Constructs Segment Routing App Config Handler.
-     *
-     * @param srManager instance of {@link SegmentRoutingManager}
-     */
-    public AppConfigHandler(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-        this.deviceService = srManager.deviceService;
-    }
-
-    /**
-     * Processes Segment Routing App Config added event.
-     *
-     * @param event network config added event
-     */
-    protected void processAppConfigAdded(NetworkConfigEvent event) {
-        log.info("Processing AppConfig CONFIG_ADDED");
-        SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
-        deviceService.getAvailableDevices().forEach(device -> {
-            populateVRouter(device.id(), getMacAddresses(config));
-            config.blackholeIPs().forEach(ipPrefix -> {
-                srManager.routingRulePopulator.populateDefaultRouteBlackhole(device.id(), ipPrefix);
-            });
-        });
-    }
-
-    /**
-     * Processes Segment Routing App Config updated event.
-     *
-     * @param event network config updated event
-     */
-    protected void processAppConfigUpdated(NetworkConfigEvent event) {
-        log.info("Processing AppConfig CONFIG_UPDATED");
-        SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
-        SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
-        deviceService.getAvailableDevices().forEach(device -> {
-            Set<MacAddress> macAddresses = new HashSet<>(getMacAddresses(config));
-            Set<MacAddress> prevMacAddresses = new HashSet<>(getMacAddresses(prevConfig));
-            // Avoid removing and re-adding unchanged MAC addresses since
-            // FlowObjective does not guarantee the execution order.
-            Set<MacAddress> sameMacAddresses = new HashSet<>(macAddresses);
-            sameMacAddresses.retainAll(prevMacAddresses);
-            macAddresses.removeAll(sameMacAddresses);
-            prevMacAddresses.removeAll(sameMacAddresses);
-
-            revokeVRouter(device.id(), prevMacAddresses);
-            populateVRouter(device.id(), macAddresses);
-            Set<IpPrefix> toRemove = Sets.difference(prevConfig.blackholeIPs(), config.blackholeIPs());
-            toRemove.forEach(ipPrefix -> {
-                srManager.routingRulePopulator.removeDefaultRouteBlackhole(device.id(), ipPrefix);
-            });
-            Set<IpPrefix> toAdd = Sets.difference(config.blackholeIPs(), prevConfig.blackholeIPs());
-            toAdd.forEach(ipPrefix -> {
-                srManager.routingRulePopulator.populateDefaultRouteBlackhole(device.id(), ipPrefix);
-            });
-        });
-
-    }
-
-    /**
-     * Processes Segment Routing App Config removed event.
-     *
-     * @param event network config removed event
-     */
-    protected void processAppConfigRemoved(NetworkConfigEvent event) {
-        log.info("Processing AppConfig CONFIG_REMOVED");
-        SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
-        deviceService.getAvailableDevices().forEach(device -> {
-            revokeVRouter(device.id(), getMacAddresses(prevConfig));
-            prevConfig.blackholeIPs().forEach(ipPrefix -> {
-                srManager.routingRulePopulator.removeDefaultRouteBlackhole(device.id(), ipPrefix);
-            });
-        });
-    }
-
-    /**
-     * Populates initial vRouter and blackhole rules.
-     *
-     * @param deviceId device ID
-     */
-    public void init(DeviceId deviceId) {
-        SegmentRoutingAppConfig config =
-                srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
-        populateVRouter(deviceId, getMacAddresses(config));
-        if (config != null) {
-            config.blackholeIPs().forEach(ipPrefix -> {
-                srManager.routingRulePopulator.populateDefaultRouteBlackhole(deviceId, ipPrefix);
-            });
-        }
-    }
-
-    private void populateVRouter(DeviceId deviceId, Set<MacAddress> pendingAdd) {
-        if (!isEdge(deviceId)) {
-            return;
-        }
-        getVRouterFlowObjBuilders(pendingAdd).forEach(foBuilder -> {
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("vRouterMac filter for {} populated", pendingAdd),
-                    (objective, error) ->
-                            log.warn("Failed to populate vRouterMac filter for {}: {}", pendingAdd, error));
-            srManager.flowObjectiveService.filter(deviceId, foBuilder.add(context));
-        });
-    }
-
-    private void revokeVRouter(DeviceId deviceId, Set<MacAddress> pendingRemove) {
-        if (!isEdge(deviceId)) {
-            return;
-        }
-        getVRouterFlowObjBuilders(pendingRemove).forEach(foBuilder -> {
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("vRouterMac filter for {} revoked", pendingRemove),
-                    (objective, error) ->
-                            log.warn("Failed to revoke vRouterMac filter for {}: {}", pendingRemove, error));
-            srManager.flowObjectiveService.filter(deviceId, foBuilder.remove(context));
-        });
-    }
-
-    private Set<FilteringObjective.Builder> getVRouterFlowObjBuilders(Set<MacAddress> macAddresses) {
-        ImmutableSet.Builder<FilteringObjective.Builder> setBuilder = ImmutableSet.builder();
-        macAddresses.forEach(macAddress -> {
-            FilteringObjective.Builder fobuilder = DefaultFilteringObjective.builder();
-            fobuilder.withKey(Criteria.matchInPort(PortNumber.ANY))
-                    .addCondition(Criteria.matchEthDst(macAddress))
-                    .permit()
-                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                    .fromApp(srManager.appId);
-            setBuilder.add(fobuilder);
-        });
-        return setBuilder.build();
-    }
-
-    private Set<MacAddress> getMacAddresses(SegmentRoutingAppConfig config) {
-        if (config == null) {
-            return ImmutableSet.of();
-        }
-        return ImmutableSet.copyOf(config.vRouterMacs());
-    }
-
-    private boolean isEdge(DeviceId deviceId) {
-        try {
-            if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {
-                return true;
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn("Device configuration for {} is not present.", deviceId);
-        }
-        return false;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
deleted file mode 100644
index cfef0f1..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * 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 org.onlab.packet.ARP;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.host.HostService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.onosproject.net.neighbour.NeighbourMessageType.REQUEST;
-
-/**
- * Handler of ARP packets that responses or forwards ARP packets that
- * are sent to the controller.
- */
-public class ArpHandler extends SegmentRoutingNeighbourHandler {
-
-    private static Logger log = LoggerFactory.getLogger(ArpHandler.class);
-
-    /**
-     * Creates an ArpHandler object.
-     *
-     * @param srManager SegmentRoutingManager object
-     */
-    public ArpHandler(SegmentRoutingManager srManager) {
-        super(srManager);
-    }
-
-    /**
-     * Processes incoming ARP packets.
-     *
-     * If it is an ARP request to router itself or known hosts,
-     * then it sends ARP response.
-     * If it is an ARP request to unknown hosts in its own subnet,
-     * then it flood the ARP request to the ports.
-     * If it is an ARP response, then set a flow rule for the host
-     * and forward any IP packets to the host in the packet buffer to the host.
-     * <p>
-     * Note: We handles all ARP packet in, even for those ARP packets between
-     * hosts in the same subnet.
-     * For an ARP packet with broadcast destination MAC,
-     * some switches pipelines will send it to the controller due to table miss,
-     * other switches will flood the packets directly in the data plane without
-     * packet in.
-     * We can deal with both cases.
-     *
-     * @param pkt incoming ARP packet and context information
-     * @param hostService the host service
-     */
-    public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {
-
-        SegmentRoutingAppConfig appConfig = srManager.cfgService
-                .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
-        if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
-            // Ignore ARP packets come from suppressed ports
-            pkt.drop();
-            return;
-        }
-
-        if (!validateArpSpa(pkt)) {
-            log.debug("Ignore ARP packet discovered on {} with unexpected src protocol address {}.",
-                    pkt.inPort(), pkt.sender().getIp4Address());
-            pkt.drop();
-            return;
-        }
-
-        if (pkt.type() == REQUEST) {
-            handleArpRequest(pkt, hostService);
-        } else {
-            handleArpReply(pkt, hostService);
-        }
-    }
-
-    private void handleArpRequest(NeighbourMessageContext pkt, HostService hostService) {
-        // ARP request for router. Send ARP reply.
-        if (isArpForRouter(pkt)) {
-            MacAddress targetMac = config.getRouterMacForAGatewayIp(pkt.target().getIp4Address());
-            if (targetMac == null) {
-                log.warn("Router MAC of {} is not configured. Cannot handle ARP request from {}",
-                        pkt.inPort().deviceId(), pkt.sender());
-                return;
-            }
-            sendResponse(pkt, targetMac, hostService, true);
-        } else {
-            // NOTE: Ignore ARP packets except those target for the router
-            //       We will reconsider enabling this when we have host learning support
-            /*
-            Set<Host> hosts = hostService.getHostsByIp(pkt.target());
-            if (hosts.size() > 1) {
-                log.warn("More than one host with the same ip {}", pkt.target());
-            }
-            Host targetHost = hosts.stream().findFirst().orElse(null);
-            // ARP request for known hosts. Send proxy ARP reply on behalf of the target.
-            if (targetHost != null) {
-                pkt.forward(targetHost.location());
-            // ARP request for unknown host in the subnet. Flood in the subnet.
-            } else {
-                flood(pkt);
-            }
-            */
-        }
-    }
-
-    private void handleArpReply(NeighbourMessageContext pkt, HostService hostService) {
-        // ARP reply for router. Process all pending IP packets.
-        if (isArpForRouter(pkt)) {
-            Ip4Address hostIpAddress = pkt.sender().getIp4Address();
-            srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
-        } else {
-            // NOTE: Ignore ARP packets except those target for the router
-            //       We will reconsider enabling this when we have host learning support
-            /*
-            HostId targetHostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
-            Host targetHost = hostService.getHost(targetHostId);
-            // ARP reply for known hosts. Forward to the host.
-            if (targetHost != null) {
-                pkt.forward(targetHost.location());
-            // ARP reply for unknown host, Flood in the subnet.
-            } else {
-                // Don't flood to non-edge ports
-                if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
-                    return;
-                }
-                flood(pkt);
-            }
-            */
-        }
-    }
-
-    /**
-     * Check if the source protocol address of an ARP packet belongs to the same
-     * subnet configured on the port it is seen.
-     *
-     * @param pkt ARP packet and context information
-     * @return true if the source protocol address belongs to the configured subnet
-     */
-    private boolean validateArpSpa(NeighbourMessageContext pkt) {
-        Ip4Address spa = pkt.sender().getIp4Address();
-        Set<IpPrefix> subnet = config.getPortSubnets(pkt.inPort().deviceId(), pkt.inPort().port())
-                .stream()
-                .filter(ipPrefix -> ipPrefix.isIp4() && ipPrefix.contains(spa))
-                .collect(Collectors.toSet());
-        return !subnet.isEmpty();
-    }
-
-
-    private boolean isArpForRouter(NeighbourMessageContext pkt) {
-        Ip4Address targetProtocolAddress = pkt.target().getIp4Address();
-        Set<IpAddress> gatewayIpAddresses = null;
-        try {
-            if (targetProtocolAddress.equals(config.getRouterIpv4(pkt.inPort().deviceId()))) {
-                return true;
-            }
-            gatewayIpAddresses = config.getPortIPs(pkt.inPort().deviceId());
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting check for router IP in processing arp");
-        }
-        if (gatewayIpAddresses != null &&
-                gatewayIpAddresses.contains(targetProtocolAddress)) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Sends an APR request for the target IP address to all ports except in-port.
-     *
-     * @param deviceId Switch device ID
-     * @param targetAddress target IP address for ARP
-     * @param inPort in-port
-     */
-    public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
-        byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
-        byte[] senderIpAddress = new byte[Ip4Address.BYTE_LENGTH];
-        /*
-         * Retrieves device info.
-         */
-        if (!getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress)) {
-            log.warn("Aborting sendArpRequest, we cannot get all the information needed");
-            return;
-        }
-        /*
-         * Creates the request.
-         */
-        Ethernet arpRequest = ARP.buildArpRequest(
-                senderMacAddress,
-                senderIpAddress,
-                targetAddress.toOctets(),
-                VlanId.NO_VID
-        );
-        flood(arpRequest, inPort, targetAddress);
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
deleted file mode 100644
index 8b4b31c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ /dev/null
@@ -1,2222 +0,0 @@
-/*
- * 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.net.flowobjective.Objective;
-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.ConsistentMultimap;
-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.Map.Entry;
-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;
-
-    // Distributed routes store to keep track of the routes already seen
-    // destination device is the key and target sw is the value
-    ConsistentMultimap<DeviceId, DeviceId> seenBeforeRoutes;
-
-    // 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.seenBeforeRoutes = srManager.storageService.<DeviceId, DeviceId>consistentMultimapBuilder()
-                .withName("programmed-routes")
-                .withSerializer(Serializer.using(KryoNamespaces.API))
-                .withRelaxedReadConsistency()
-                .build();
-        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
-    * STABILITY_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));
-                    }
-                }
-            }
-
-            log.debug("seenBeforeRoutes size {}", seenBeforeRoutes.size());
-            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());
-                }
-            });
-            log.debug("seenBeforeRoutes size {}", seenBeforeRoutes.size());
-            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");
-            log.debug("seenBeforeRoutes size {}", seenBeforeRoutes.size());
-            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
-                if (linkUp != null) {
-                    // deal with linkUp of a seen-before link
-                    if (seenBefore) {
-                        // link previously seen before
-                        // do hash-bucket changes instead of a re-route
-                        processHashGroupChangeForLinkUp(routeChanges);
-                        // clear out routesChanges so a re-route is not attempted
-                        routeChanges = ImmutableSet.of();
-                        hashGroupsChanged = true;
-                    } else {
-                        // do hash-bucket changes first, method will return changed routes;
-                        // for each route not changed it will perform a reroute
-                        Set<ArrayList<DeviceId>> changedRoutes = processHashGroupChangeForLinkUp(routeChanges);
-                        Set<ArrayList<DeviceId>> routeChangesTemp = getExpandedRoutes(routeChanges);
-                        changedRoutes.forEach(routeChangesTemp::remove);
-                        // if routesChanges is empty a re-route is not attempted
-                        routeChanges = routeChangesTemp;
-                        for (ArrayList<DeviceId> route : routeChanges) {
-                            log.debug("remaining routes Target -> Root");
-                            if (route.size() == 1) {
-                                log.debug(" : all -> {}", route.get(0));
-                            } else {
-                                log.debug(" : {} -> {}", route.get(0), route.get(1));
-                            }
-                        }
-                        // Mark hash groups as changed
-                        if (!changedRoutes.isEmpty()) {
-                            hashGroupsChanged = true;
-                        }
-                    }
-
-                }
-
-                //deal with switchDown
-                if (switchDown != null) {
-                    processHashGroupChangeForFailure(routeChanges, 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);
-                processHashGroupChangeForFailure(routeChanges, 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;
-            }
-
-            if (hashGroupsChanged) {
-                log.debug("Hash-groups changed for link status change");
-            }
-
-            // 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 = getExpandedRoutes(routeChanges);
-        // no valid routes - fail fast
-        if (changedRoutes.isEmpty()) {
-            return false;
-        }
-
-        // Temporary stores the changed routes
-        Set<ArrayList<DeviceId>> tempRoutes = ImmutableSet.copyOf(changedRoutes);
-        // now process changedRoutes according to edgePairs
-        if (!redoRoutingEdgePairs(edgePairs, subnets, changedRoutes)) {
-            return false; //abort routing and fail fast
-        }
-        // Calculate the programmed routes pointing to the pairs
-        Set<ArrayList<DeviceId>> programmedPairRoutes = Sets.difference(tempRoutes, changedRoutes);
-        log.debug("Evaluating programmed pair routes");
-        storeSeenBeforeRoutes(programmedPairRoutes);
-
-        // Temporary stores the left routes
-        tempRoutes = ImmutableSet.copyOf(changedRoutes);
-        // 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
-        }
-        // Calculate the individual programmed routes
-        Set<ArrayList<DeviceId>> programmedIndividualRoutes = Sets.difference(tempRoutes, changedRoutes);
-        log.debug("Evaluating individual programmed routes");
-        storeSeenBeforeRoutes(programmedIndividualRoutes);
-
-        // 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;
-    }
-
-    /**
-     * Stores the routes seen before. Routes are two-elements arrays.
-     * @param seenRoutes seen before routes
-     */
-    private void storeSeenBeforeRoutes(Set<ArrayList<DeviceId>> seenRoutes) {
-        Set<DeviceId> nextHops;
-        for (ArrayList<DeviceId> route : seenRoutes) {
-            log.debug("Route {} -> {} has been programmed", route.get(0), route.get(1));
-            nextHops = getNextHops(route.get(0), route.get(1));
-            // No valid next hops - cannot be considered a programmed route
-            if (nextHops.isEmpty()) {
-                log.debug("Could not find next hop from target:{} --> dst {} "
-                                  + "skipping this route", route.get(0), route.get(1));
-                continue;
-            }
-            // Already present - do not add again
-            if (seenBeforeRoutes.containsEntry(route.get(1), route.get(0))) {
-                log.debug("Route from target:{} --> dst {} " +
-                                  "already present, skipping this route", route.get(0), route.get(1));
-                continue;
-            }
-            seenBeforeRoutes.put(route.get(1), route.get(0));
-        }
-    }
-
-    /**
-     * 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 (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)));
-                changedRoutes.remove(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 due to a switch/link failure 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 failedSwitch the switchId if the route changes are for a failed switch,
-     *                     otherwise null
-     */
-    private void processHashGroupChangeForFailure(Set<ArrayList<DeviceId>> routeChanges,
-                                                  DeviceId failedSwitch) {
-        // first, ensure each routeChanges entry has two elements
-        Set<ArrayList<DeviceId>> changedRoutes = getAllExpandedRoutes(routeChanges);
-        boolean someFailed = false;
-        boolean success;
-        Set<DeviceId> updatedDevices = Sets.newHashSet();
-        for (ArrayList<DeviceId> route : changedRoutes) {
-            DeviceId targetSw = route.get(0);
-            DeviceId dstSw = route.get(1);
-            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;
-            }
-        }
-        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);
-            });
-        }
-    }
-
-    /**
-     * Processes a set a route-path changes due to link up 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.
-     * @return set of changed routes
-     */
-    private Set<ArrayList<DeviceId>> processHashGroupChangeForLinkUp(Set<ArrayList<DeviceId>> routeChanges) {
-        // Stores changed routes
-        Set<ArrayList<DeviceId>> doneRoutes = new HashSet<>();
-        // first, ensure each routeChanges entry has two elements
-        Set<ArrayList<DeviceId>> changedRoutes = getAllExpandedRoutes(routeChanges);
-        boolean someFailed = false;
-        boolean success;
-        Set<DeviceId> updatedDevices = Sets.newHashSet();
-        for (ArrayList<DeviceId> route : changedRoutes) {
-            DeviceId targetSw = route.get(0);
-            DeviceId dstSw = route.get(1);
-            // linkup - fix (if possible)
-            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);
-                doneRoutes.add(route);
-            } 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);
-                    });
-        }
-        return doneRoutes;
-    }
-
-    /**
-     * 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);
-        if (!seenBeforeRoutes.containsEntry(destSw, targetSw)) {
-            log.warn("Cannot fixHashGroupsForRoute {} -> {} has not been programmed before",
-                     targetSw, destSw);
-            return false;
-        }
-        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);
-    }
-
-    /**
-     * Revoke rules of given subnets in the given switches.
-     *
-     * @param targetSwitches switched from which subnets to be removed
-     * @param subnets subnet bring removed
-     * @return true if succeed
-     */
-    protected boolean revokeSubnet(Set<DeviceId> targetSwitches, Set<IpPrefix> subnets) {
-        List<Future<Boolean>> futures = Lists.newArrayList();
-        for (DeviceId targetSw : targetSwitches) {
-            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
-     * @return future that includes the flow objective if succeeded, null if otherwise
-     */
-    CompletableFuture<Objective> populateRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
-                                               VlanId hostVlanId, PortNumber outPort, boolean directHost) {
-        if (shouldProgram(deviceId)) {
-            return srManager.routingRulePopulator.populateRoute(deviceId, prefix,
-                    hostMac, hostVlanId, outPort, directHost);
-        }
-        return CompletableFuture.completedFuture(null);
-    }
-
-    /**
-     * 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
-     * @return future that carries the flow objective if succeeded, null if otherwise
-     */
-    CompletableFuture<Objective> revokeRoute(DeviceId deviceId, IpPrefix prefix,
-                     MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
-        if (shouldProgram(deviceId)) {
-            return srManager.routingRulePopulator.revokeRoute(deviceId, prefix, hostMac, hostVlanId,
-                    outPort, directHost);
-        }
-        return CompletableFuture.completedFuture(null);
-    }
-
-    CompletableFuture<Objective> populateBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
-        if (shouldProgram(deviceId)) {
-            return srManager.routingRulePopulator.populateBridging(deviceId, port, mac, vlanId);
-        }
-        return CompletableFuture.completedFuture(null);
-    }
-
-    CompletableFuture<Objective> revokeBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
-        if (shouldProgram(deviceId)) {
-            return srManager.routingRulePopulator.revokeBridging(deviceId, port, mac, vlanId);
-        }
-        return CompletableFuture.completedFuture(null);
-    }
-
-    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);
-    }
-
-    /**
-     * Purges seen before routes for a given device.
-     * @param deviceId the device id
-     */
-    void purgeSeenBeforeRoutes(DeviceId deviceId) {
-        log.debug("Purging seen before routes having as target {}", deviceId);
-        Set<Entry<DeviceId, DeviceId>> routesToPurge = seenBeforeRoutes.stream()
-                .filter(entry -> entry.getValue().equals(deviceId))
-                .collect(Collectors.toSet());
-        routesToPurge.forEach(entry -> seenBeforeRoutes.remove(entry.getKey(), entry.getValue()));
-    }
-
-    /**
-     * 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());
-                            seenBeforeRoutes.removeAll(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;
-    }
-
-    // Utility method to expands the route changes in two elements array using
-    // the ECMP graph. Caller represents all to dst switch routes with an
-    // array containing only the dst switch.
-    private Set<ArrayList<DeviceId>> getExpandedRoutes(Set<ArrayList<DeviceId>> routeChanges) {
-        Set<ArrayList<DeviceId>> changedRoutes = new HashSet<>();
-        // Ensure each routeChanges entry has two elements
-        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 Collections.emptySet();
-                }
-                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));
-            }
-        }
-        return changedRoutes;
-    }
-
-    // Utility method to expands the route changes in two elements array using
-    // the available devices. Caller represents all to dst switch routes with an
-    // array containing only the dst switch.
-    private Set<ArrayList<DeviceId>> getAllExpandedRoutes(Set<ArrayList<DeviceId>> routeChanges) {
-        Set<ArrayList<DeviceId>> changedRoutes = new HashSet<>();
-        // 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);
-            }
-        }
-        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;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
deleted file mode 100644
index 0fd7c077..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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 java.util.List;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Default Tunnel class.
- */
-public class DefaultTunnel implements Tunnel {
-
-    private final String id;
-    private final List<Integer> labelIds;
-
-    private int groupId;
-    private boolean allowedToRemoveGroup;
-
-    /**
-     * Creates a Tunnel reference.
-     *
-     * @param tid  Tunnel ID
-     * @param labelIds Label stack of the tunnel
-     */
-    public DefaultTunnel(String tid, List<Integer> labelIds) {
-        this.id = checkNotNull(tid);
-        this.labelIds = labelIds;
-        //TODO: need to register the class in Kryo for this
-        //this.labelIds = Collections.unmodifiableList(labelIds);
-        this.groupId = -1;
-    }
-
-    /**
-     * Creates a new DefaultTunnel reference using the tunnel reference.
-     *
-     * @param tunnel DefaultTunnel reference
-     */
-    public DefaultTunnel(DefaultTunnel tunnel) {
-        this.id = tunnel.id;
-        this.labelIds = tunnel.labelIds;
-        this.groupId = tunnel.groupId;
-    }
-
-    @Override
-    public String id() {
-        return this.id;
-    }
-
-    @Override
-    public List<Integer> labelIds() {
-        return this.labelIds;
-    }
-
-    @Override
-    public int groupId() {
-        return this.groupId;
-    }
-
-    @Override
-    public void setGroupId(int id) {
-        this.groupId = id;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (o instanceof DefaultTunnel) {
-            DefaultTunnel tunnel = (DefaultTunnel) o;
-            // We compare only the tunnel paths.
-            if (tunnel.labelIds.equals(this.labelIds)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return labelIds.hashCode();
-    }
-
-    @Override
-    public boolean isAllowedToRemoveGroup() {
-        return this.allowedToRemoveGroup;
-    }
-
-    @Override
-    public void allowToRemoveGroup(boolean b) {
-        this.allowedToRemoveGroup = b;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java
deleted file mode 100644
index 036044c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * 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 org.onlab.graph.ScalarWeight;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.provider.ProviderId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Set;
-
-/**
- * This class creates breadth-first-search (BFS) tree for a given root device
- * and returns paths from the root Device to leaf Devices (target devices).
- * The paths are snapshot paths at the point of the class instantiation.
- */
-public class EcmpShortestPathGraph {
-    LinkedList<DeviceId> deviceQueue = new LinkedList<>();
-    LinkedList<Integer> distanceQueue = new LinkedList<>();
-    HashMap<DeviceId, Integer> deviceSearched = new HashMap<>();
-    HashMap<DeviceId, ArrayList<Link>> upstreamLinks = new HashMap<>();
-    HashMap<DeviceId, ArrayList<Path>> paths = new HashMap<>();
-    HashMap<Integer, ArrayList<DeviceId>> distanceDeviceMap = new HashMap<>();
-    DeviceId rootDevice;
-    private SegmentRoutingManager srManager;
-    private static final Logger log = LoggerFactory.getLogger(EcmpShortestPathGraph.class);
-
-    /**
-     * Constructor.
-     *
-     * @param rootDevice root of the BFS tree
-     * @param srManager SegmentRoutingManager object
-     */
-    public EcmpShortestPathGraph(DeviceId rootDevice, SegmentRoutingManager srManager) {
-        this.rootDevice = rootDevice;
-        this.srManager = srManager;
-        calcECMPShortestPathGraph();
-    }
-
-    /**
-     * Calculates the BFS tree.
-     */
-   private void calcECMPShortestPathGraph() {
-        deviceQueue.add(rootDevice);
-        int currDistance = 0;
-        distanceQueue.add(currDistance);
-        deviceSearched.put(rootDevice, currDistance);
-        while (!deviceQueue.isEmpty()) {
-            DeviceId sw = deviceQueue.poll();
-            Set<DeviceId> prevSw = Sets.newHashSet();
-            currDistance = distanceQueue.poll();
-
-            for (Link link : srManager.linkHandler.getDeviceEgressLinks(sw)) {
-                if (srManager.linkHandler.avoidLink(link)) {
-                    continue;
-                }
-                DeviceId reachedDevice = link.dst().deviceId();
-                if (prevSw.contains(reachedDevice)) {
-                    // Ignore LAG links between the same set of Devices
-                    continue;
-                } else  {
-                    prevSw.add(reachedDevice);
-                }
-
-                Integer distance = deviceSearched.get(reachedDevice);
-                if ((distance != null) && (distance < (currDistance + 1))) {
-                    continue;
-                }
-                if (distance == null) {
-                    // First time visiting this Device node
-                    deviceQueue.add(reachedDevice);
-                    distanceQueue.add(currDistance + 1);
-                    deviceSearched.put(reachedDevice, currDistance + 1);
-
-                    ArrayList<DeviceId> distanceSwArray = distanceDeviceMap
-                            .get(currDistance + 1);
-                    if (distanceSwArray == null) {
-                        distanceSwArray = new ArrayList<>();
-                        distanceSwArray.add(reachedDevice);
-                        distanceDeviceMap.put(currDistance + 1, distanceSwArray);
-                    } else {
-                        distanceSwArray.add(reachedDevice);
-                    }
-                }
-
-                ArrayList<Link> upstreamLinkArray =
-                        upstreamLinks.get(reachedDevice);
-                if (upstreamLinkArray == null) {
-                    upstreamLinkArray = new ArrayList<>();
-                    upstreamLinkArray.add(copyDefaultLink(link));
-                    //upstreamLinkArray.add(link);
-                    upstreamLinks.put(reachedDevice, upstreamLinkArray);
-                } else {
-                    // ECMP links
-                    upstreamLinkArray.add(copyDefaultLink(link));
-                }
-            }
-        }
-    }
-
-    private void getDFSPaths(DeviceId dstDeviceDeviceId, Path path, ArrayList<Path> paths) {
-        DeviceId rootDeviceDeviceId = rootDevice;
-        for (Link upstreamLink : upstreamLinks.get(dstDeviceDeviceId)) {
-            /* Deep clone the path object */
-            Path sofarPath;
-            ArrayList<Link> sofarLinks = new ArrayList<>();
-            if (path != null && !path.links().isEmpty()) {
-                sofarLinks.addAll(path.links());
-            }
-            sofarLinks.add(upstreamLink);
-            sofarPath = new DefaultPath(ProviderId.NONE, sofarLinks, ScalarWeight.toWeight(0));
-            if (upstreamLink.src().deviceId().equals(rootDeviceDeviceId)) {
-                paths.add(sofarPath);
-                return;
-            } else {
-                getDFSPaths(upstreamLink.src().deviceId(), sofarPath, paths);
-            }
-        }
-    }
-
-    /**
-     * Return root Device for the graph.
-     *
-     * @return root Device
-     */
-    public DeviceId getRootDevice() {
-        return rootDevice;
-    }
-
-    /**
-     * Return the computed ECMP paths from the root Device to a given Device in
-     * the network.
-     *
-     * @param targetDevice the target Device
-     * @return the list of ECMP Paths from the root Device to the target Device
-     */
-    public ArrayList<Path> getECMPPaths(DeviceId targetDevice) {
-        ArrayList<Path> pathArray = paths.get(targetDevice);
-        if (pathArray == null && deviceSearched.containsKey(
-                targetDevice)) {
-            pathArray = new ArrayList<>();
-            DeviceId sw = targetDevice;
-            getDFSPaths(sw, null, pathArray);
-            paths.put(targetDevice, pathArray);
-        }
-        return pathArray;
-    }
-
-    /**
-     * Return the complete info of the computed ECMP paths for each Device
-     * learned in multiple iterations from the root Device.
-     *
-     * @return the hash table of Devices learned in multiple Dijkstra
-     *         iterations and corresponding ECMP paths to it from the root
-     *         Device
-     */
-    public HashMap<Integer, HashMap<DeviceId,
-            ArrayList<Path>>> getCompleteLearnedDeviceesAndPaths() {
-
-        HashMap<Integer, HashMap<DeviceId, ArrayList<Path>>> pathGraph = new HashMap<>();
-
-        for (Integer itrIndx : distanceDeviceMap.keySet()) {
-            HashMap<DeviceId, ArrayList<Path>> swMap = new HashMap<>();
-            for (DeviceId sw : distanceDeviceMap.get(itrIndx)) {
-                swMap.put(sw, getECMPPaths(sw));
-            }
-            pathGraph.put(itrIndx, swMap);
-        }
-
-        return pathGraph;
-    }
-
-    /**
-     * Returns the complete info of the computed ECMP paths for each target device
-     * learned in multiple iterations from the root Device. The computed info
-     * returned is per iteration (Integer key of outer HashMap). In each
-     * iteration, for the target devices reached (DeviceId key of inner HashMap),
-     * the ECMP paths are detailed (2D array).
-     *
-     * @return the hash table of target Devices learned in multiple Dijkstra
-     *         iterations and corresponding ECMP paths in terms of Devices to
-     *         be traversed (via) from the root Device to the target Device
-     */
-    public HashMap<Integer, HashMap<DeviceId,
-            ArrayList<ArrayList<DeviceId>>>> getAllLearnedSwitchesAndVia() {
-
-        HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> deviceViaMap = new HashMap<>();
-
-        for (Integer itrIndx : distanceDeviceMap.keySet()) {
-            HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swMap = new HashMap<>();
-
-            for (DeviceId sw : distanceDeviceMap.get(itrIndx)) {
-                ArrayList<ArrayList<DeviceId>> swViaArray = new ArrayList<>();
-                for (Path path : getECMPPaths(sw)) {
-                    ArrayList<DeviceId> swVia = new ArrayList<>();
-                    for (Link link : path.links()) {
-                        if (link.src().deviceId().equals(rootDevice)) {
-                            /* No need to add the root Device again in
-                             * the Via list
-                             */
-                            continue;
-                        }
-                        swVia.add(link.src().deviceId());
-                    }
-                    swViaArray.add(swVia);
-                }
-                swMap.put(sw, swViaArray);
-            }
-            deviceViaMap.put(itrIndx, swMap);
-        }
-        return deviceViaMap;
-    }
-
-
-    private Link copyDefaultLink(Link link) {
-        DefaultLink src = (DefaultLink) link;
-        DefaultLink defaultLink = DefaultLink.builder()
-                .providerId(src.providerId())
-                .src(src.src())
-                .dst(src.dst())
-                .type(src.type())
-                .annotations(src.annotations())
-                .build();
-
-        return defaultLink;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sBuilder = new StringBuilder();
-        for (Device device: srManager.deviceService.getDevices()) {
-            if (!device.id().equals(rootDevice)) {
-                sBuilder.append("\r\n  Paths from " + rootDevice + " to "
-                                + device.id());
-                ArrayList<Path> paths = getECMPPaths(device.id());
-                if (paths != null) {
-                    for (Path path : paths) {
-                        sBuilder.append("\r\n       == "); // equal cost paths delimiter
-                        for (int i = path.links().size() - 1; i >= 0; i--) {
-                            Link link = path.links().get(i);
-                            sBuilder.append(" : " + link.src() + " -> " + link.dst());
-                        }
-                    }
-                } else {
-                    sBuilder.append("\r\n       == no paths");
-                }
-            }
-        }
-        return sBuilder.toString();
-    }
-}
-
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EdgePair.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EdgePair.java
deleted file mode 100644
index 571e87f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EdgePair.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2018-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 org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Represents two devices that are paired by configuration. An EdgePair for
- * (dev1, dev2) is the same as as EdgePair for (dev2, dev1)
- */
-public final class EdgePair {
-    DeviceId dev1;
-    DeviceId dev2;
-
-    EdgePair(DeviceId dev1, DeviceId dev2) {
-        this.dev1 = dev1;
-        this.dev2 = dev2;
-    }
-
-    boolean includes(DeviceId dev) {
-        return dev1.equals(dev) || dev2.equals(dev);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof EdgePair)) {
-            return false;
-        }
-        EdgePair that = (EdgePair) o;
-        return ((this.dev1.equals(that.dev1) && this.dev2.equals(that.dev2)) ||
-                (this.dev1.equals(that.dev2) && this.dev2.equals(that.dev1)));
-    }
-
-    @Override
-    public int hashCode() {
-        if (dev1.toString().compareTo(dev2.toString()) <= 0) {
-            return Objects.hash(dev1, dev2);
-        } else {
-            return Objects.hash(dev2, dev1);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(this)
-                .add("Dev1", dev1)
-                .add("Dev2", dev2)
-                .toString();
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
deleted file mode 100644
index 46231b0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ /dev/null
@@ -1,872 +0,0 @@
-/*
- * Copyright 2016-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.Lists;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.PredictableExecutor;
-import org.onlab.util.Tools;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.ProbeMode;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Handles host-related events.
- */
-public class HostHandler {
-    private static final Logger log = LoggerFactory.getLogger(HostHandler.class);
-
-    protected final SegmentRoutingManager srManager;
-    private HostService hostService;
-    // Host workers - 0 will leverage available processors
-    private static final int DEFAULT_THREADS = 0;
-    protected PredictableExecutor hostWorkers;
-
-    /**
-     * Constructs the HostHandler.
-     *
-     * @param srManager Segment Routing manager
-     */
-    HostHandler(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-        hostService = srManager.hostService;
-        this.hostWorkers = new PredictableExecutor(DEFAULT_THREADS,
-                                                   groupedThreads("onos/sr", "h-worker-%d", log));
-    }
-
-    /**
-     * Shutdowns the workers.
-     */
-    void terminate() {
-        hostWorkers.shutdown();
-    }
-
-    protected void init(DeviceId devId) {
-        log.info("Initializing hosts on {}", devId);
-        List<CompletableFuture<Void>> hostFutures = Lists.newArrayList();
-
-        // Init hosts in parallel using hostWorkers executor
-        hostService.getHosts().forEach(host -> {
-            hostFutures.add(hostWorkers.submit(() -> initHost(host, devId), host.id().hashCode()));
-        });
-
-        log.debug("{} hostFutures for {}", hostFutures.size(), devId);
-        CompletableFuture<Void> allHostFuture = CompletableFuture.allOf(hostFutures.toArray(new CompletableFuture[0]));
-        CompletableFuture<Void> timeoutFuture =
-                Tools.completeAfter(PhasedRecoveryService.PAIR_TIMEOUT, TimeUnit.SECONDS);
-
-        allHostFuture.runAfterEitherAsync(timeoutFuture, () -> {
-            if (allHostFuture.isDone()) {
-                log.info("{} hosts initialized. Move {} to the next phase", hostFutures.size(), devId);
-            } else {
-                log.info("Timeout reached. Move {} to the next phase", devId);
-            }
-            srManager.phasedRecoveryService.setPhase(devId, Phase.INFRA);
-        });
-    }
-
-    private void initHost(Host host, DeviceId deviceId) {
-        List<CompletableFuture<Objective>> locationFutures = Lists.newArrayList();
-
-        effectiveLocations(host).forEach(location -> {
-            if (location.deviceId().equals(deviceId) ||
-                    location.deviceId().equals(srManager.getPairDeviceId(deviceId).orElse(null))) {
-                locationFutures.addAll(processHostAddedAtLocation(host, location));
-            }
-        });
-
-        log.debug("{} locationFutures for {}", locationFutures.size(), host);
-
-        // Waiting for all locationFutures to be completed.
-        // This is a blocking operation but it is fine since this is run in a separate thread
-        try {
-            CompletableFuture.allOf(locationFutures.toArray(new CompletableFuture[0]))
-                    .thenApply(objectives -> locationFutures.stream()
-                            .map(CompletableFuture::join)
-                            .collect(Collectors.toList())
-                    )
-                    .get();
-        } catch (InterruptedException | ExecutionException e) {
-            log.warn("Exception caught when executing locationFutures");
-            locationFutures.forEach(future -> future.cancel(false));
-        }
-    }
-
-    void processHostAddedEvent(HostEvent event) {
-        Host host = event.subject();
-        hostWorkers.execute(() -> processHostAdded(host), host.id().hashCode());
-    }
-
-    private void processHostAdded(Host host) {
-        effectiveLocations(host).forEach(location -> processHostAddedAtLocation(host, location));
-        // ensure dual-homed host locations have viable uplinks
-        if (effectiveLocations(host).size() > 1 || srManager.singleHomedDown) {
-            effectiveLocations(host).forEach(loc -> {
-                if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
-                    srManager.linkHandler.checkUplinksForHost(loc);
-                }
-            });
-        }
-    }
-
-    List<CompletableFuture<Objective>> processHostAddedAtLocation(Host host, HostLocation location) {
-        checkArgument(effectiveLocations(host).contains(location), "{} is not a location of {}", location, host);
-
-        MacAddress hostMac = host.mac();
-        VlanId hostVlanId = host.vlan();
-        Set<HostLocation> locations = effectiveLocations(host);
-        Set<IpAddress> ips = host.ipAddresses();
-        log.info("Host {}/{} is added at {}", hostMac, hostVlanId, locations);
-
-        List<CompletableFuture<Objective>> objectiveFutures = Lists.newArrayList();
-
-        // TODO Phased recovery does not trace double tagged hosts
-        if (isDoubleTaggedHost(host)) {
-            ips.forEach(ip ->
-                processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
-                                               host.innerVlan(), hostVlanId, host.tpid(), ip, false)
-            );
-        } else {
-            objectiveFutures.add(
-                    processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, false)
-            );
-            ips.forEach(ip ->
-                objectiveFutures.add(
-                        processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, false)
-                )
-            );
-        }
-
-        // Use the pair link temporarily before the second location of a dual-homed host shows up.
-        // This do not affect single-homed hosts since the flow will be blocked in
-        // processBridgingRule or processRoutingRule due to VLAN or IP mismatch respectively
-        srManager.getPairDeviceId(location.deviceId()).ifPresent(pairDeviceId -> {
-            if (effectiveLocations(host).stream().noneMatch(l -> l.deviceId().equals(pairDeviceId))) {
-                srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort -> {
-                    // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
-                    //       when the host is untagged
-                    VlanId vlanId = vlanForPairPort(hostVlanId, location);
-                    if (vlanId == null) {
-                        return;
-                    }
-
-                    objectiveFutures.add(
-                            processBridgingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, false)
-                    );
-                    ips.forEach(ip ->
-                            objectiveFutures.add(
-                                    processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, false)
-                            )
-                    );
-
-                    if (srManager.activeProbing) {
-                        probe(host, location, pairDeviceId, pairRemotePort);
-                    }
-                });
-            }
-        });
-
-        int nextId = srManager.getMacVlanNextObjectiveId(location.deviceId(), hostMac, hostVlanId, null, false);
-        if (nextId != -1) {
-            VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
-            log.debug(" Updating next objective for device {}, host {}/{}, port {}, nextid {}",
-                                location.deviceId(), hostMac, vlanId, location.port(), nextId);
-            srManager.updateMacVlanTreatment(location.deviceId(), hostMac, vlanId,
-                                location.port(), nextId);
-        }
-
-        log.debug("{} objectiveFutures for {}", objectiveFutures.size(), location);
-        return objectiveFutures;
-    }
-
-    void processHostRemovedEvent(HostEvent event) {
-        Host host = event.subject();
-        hostWorkers.execute(() -> processHostRemoved(host), host.id().hashCode());
-    }
-
-    private void processHostRemoved(Host host) {
-        MacAddress hostMac = host.mac();
-        VlanId hostVlanId = host.vlan();
-        Set<HostLocation> locations = effectiveLocations(host);
-        Set<IpAddress> ips = host.ipAddresses();
-        log.info("Host {}/{} is removed from {}", hostMac, hostVlanId, locations);
-
-        locations.forEach(location -> {
-            if (isDoubleTaggedHost(host)) {
-                ips.forEach(ip ->
-                    processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
-                                                   host.innerVlan(), hostVlanId, host.tpid(), ip, true)
-                );
-            } else {
-                processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, true);
-                ips.forEach(ip ->
-                    processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, true)
-                );
-            }
-
-            // Also remove redirection flows on the pair device if exists.
-            Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
-            Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(location.deviceId());
-            if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
-                // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
-                //       when the host is untagged
-                VlanId vlanId = vlanForPairPort(hostVlanId, location);
-                if (vlanId == null) {
-                    return;
-                }
-
-                processBridgingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId, true);
-                ips.forEach(ip ->
-                        processRoutingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId,
-                                ip, true));
-            }
-
-            // Delete prefix from sr-device-subnet when the next hop host is removed
-            srManager.routeService.getRouteTables().forEach(tableId -> {
-                srManager.routeService.getRoutes(tableId).forEach(routeInfo -> {
-                    if (routeInfo.allRoutes().stream().anyMatch(rr -> ips.contains(rr.nextHop()))) {
-                        log.debug("HostRemoved. removeSubnet {}, {}", location, routeInfo.prefix());
-                        srManager.deviceConfiguration.removeSubnet(location, routeInfo.prefix());
-                    }
-                });
-            });
-
-        });
-    }
-
-    void processHostMovedEvent(HostEvent event) {
-        Host host = event.subject();
-        hostWorkers.execute(() -> processHostMovedEventInternal(event), host.id().hashCode());
-    }
-
-    private void processHostMovedEventInternal(HostEvent event) {
-        // This method will be called when one of the following value has changed:
-        // (1) locations (2) auxLocations or (3) both locations and auxLocations.
-        // We only need to proceed when effectiveLocation has changed.
-        Set<HostLocation> newLocations = effectiveLocations(event.subject());
-        Set<HostLocation> prevLocations = effectiveLocations(event.prevSubject());
-
-        if (newLocations.equals(prevLocations)) {
-            log.info("effectiveLocations of {} has not changed. Skipping {}", event.subject().id(), event);
-            return;
-        }
-
-        Host host = event.subject();
-        Host prevHost = event.prevSubject();
-        MacAddress hostMac = host.mac();
-        VlanId hostVlanId = host.vlan();
-        Set<IpAddress> prevIps = prevHost.ipAddresses();
-        Set<IpAddress> newIps = host.ipAddresses();
-        EthType hostTpid = host.tpid();
-        boolean doubleTaggedHost = isDoubleTaggedHost(host);
-
-        log.info("Host {}/{} is moved from {} to {}", hostMac, hostVlanId, prevLocations, newLocations);
-        Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId)
-                .collect(Collectors.toSet());
-
-        // For each old location
-        Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
-            // Remove routing rules for old IPs
-            Sets.difference(prevIps, newIps).forEach(ip -> {
-                if (doubleTaggedHost) {
-                    processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(),
-                                                   hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
-                } else {
-                    processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
-                                       ip, true);
-                }
-            });
-
-            // Redirect the flows to pair link if configured
-            // Note: Do not continue removing any rule
-            Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId());
-            Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(prevLocation.deviceId());
-            if (pairDeviceId.isPresent() && pairLocalPort.isPresent() &&
-                    newLocations.stream().anyMatch(location -> location.deviceId().equals(pairDeviceId.get())) &&
-                    newLocations.stream().noneMatch(location -> location.deviceId().equals(prevLocation.deviceId()))) {
-                // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
-                //       when the host is untagged
-                VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(prevLocation)).orElse(hostVlanId);
-
-                processBridgingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId, false);
-                newIps.forEach(ip ->
-                        processRoutingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId,
-                            ip, false));
-                return;
-            }
-
-            // Remove flows for unchanged IPs only when the host moves from a switch to another.
-            // Otherwise, do not remove and let the adding part update the old flow
-            if (!newDeviceIds.contains(prevLocation.deviceId())) {
-                processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
-                Sets.intersection(prevIps, newIps).forEach(ip -> {
-                    if (doubleTaggedHost) {
-                        processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(),
-                                                       hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
-                    } else {
-                        processRoutingRule(prevLocation.deviceId(), prevLocation.port(),
-                                           hostMac, hostVlanId, ip, true);
-                    }
-                });
-            }
-
-            // Remove bridging rules if new interface vlan is different from old interface vlan
-            // Otherwise, do not remove and let the adding part update the old flow
-            if (newLocations.stream().noneMatch(newLocation -> {
-                VlanId oldAssignedVlan = srManager.getInternalVlanId(prevLocation);
-                VlanId newAssignedVlan = srManager.getInternalVlanId(newLocation);
-                // Host is tagged and the new location has the host vlan in vlan-tagged
-                return srManager.interfaceService.getTaggedVlanId(newLocation).contains(hostVlanId) ||
-                        (oldAssignedVlan != null && newAssignedVlan != null &&
-                        // Host is untagged and the new location has the same assigned vlan
-                        oldAssignedVlan.equals(newAssignedVlan));
-            })) {
-                processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
-            }
-
-            // Remove routing rules for unchanged IPs if none of the subnet of new location contains
-            // the IP. Otherwise, do not remove and let the adding part update the old flow
-            Sets.intersection(prevIps, newIps).forEach(ip -> {
-                if (newLocations.stream().noneMatch(newLocation ->
-                        srManager.deviceConfiguration.inSameSubnet(newLocation, ip))) {
-                    if (doubleTaggedHost) {
-                        processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(),
-                                                       hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
-                    } else {
-                        processRoutingRule(prevLocation.deviceId(), prevLocation.port(),
-                                           hostMac, hostVlanId, ip, true);
-                    }
-                }
-            });
-        });
-
-        // For each new location, add all new IPs.
-        Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
-            processBridgingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, false);
-            newIps.forEach(ip -> {
-                if (doubleTaggedHost) {
-                    processDoubleTaggedRoutingRule(newLocation.deviceId(), newLocation.port(),
-                                                   hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, false);
-                } else {
-                    processRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId,
-                                       ip, false);
-                }
-            });
-
-            // Probe on pair device when host move
-            // Majorly for the 2nd step of [1A/x, 1B/x] -> [1A/x, 1B/y] -> [1A/y, 1B/y]
-            // But will also cover [1A/x] -> [1A/y] -> [1A/y, 1B/y]
-            if (srManager.activeProbing) {
-
-                srManager.getPairDeviceId(newLocation.deviceId()).ifPresent(pairDeviceId ->
-                        srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort ->
-                                probe(host, newLocation, pairDeviceId, pairRemotePort)
-                        )
-                );
-            }
-        });
-
-        // For each unchanged location, add new IPs and remove old IPs.
-        Sets.intersection(newLocations, prevLocations).forEach(unchangedLocation -> {
-            Sets.difference(prevIps, newIps).forEach(ip -> {
-                 if (doubleTaggedHost) {
-                     processDoubleTaggedRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
-                                                    hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
-                 } else {
-                     processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
-                                        hostMac, hostVlanId, ip, true);
-                 }
-            });
-
-            Sets.difference(newIps, prevIps).forEach(ip -> {
-                if (doubleTaggedHost) {
-                    processDoubleTaggedRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
-                                                   hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, false);
-                } else {
-                    processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
-                                       hostMac, hostVlanId, ip, false);
-                }
-            });
-
-            // Verify existing location and see if it is still valid
-            srManager.probingService.probeHost(host, unchangedLocation, ProbeMode.VERIFY);
-        });
-
-        // ensure dual-homed host locations have viable uplinks
-        if (newLocations.size() > prevLocations.size() || srManager.singleHomedDown) {
-            newLocations.forEach(loc -> {
-                if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
-                    srManager.linkHandler.checkUplinksForHost(loc);
-                }
-            });
-        }
-    }
-
-    void processHostUpdatedEvent(HostEvent event) {
-        Host host = event.subject();
-        hostWorkers.execute(() -> processHostUpdatedEventInternal(event), host.id().hashCode());
-    }
-
-    private void processHostUpdatedEventInternal(HostEvent event) {
-        Host host = event.subject();
-        MacAddress hostMac = host.mac();
-        VlanId hostVlanId = host.vlan();
-        EthType hostTpid = host.tpid();
-        Set<HostLocation> locations = effectiveLocations(host);
-        Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
-        Set<IpAddress> newIps = host.ipAddresses();
-        log.info("Host {}/{} is updated", hostMac, hostVlanId);
-
-        locations.forEach(location -> {
-            Sets.difference(prevIps, newIps).forEach(ip -> {
-                if (isDoubleTaggedHost(host)) {
-                    processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
-                                                   host.innerVlan(), hostVlanId, hostTpid, ip, true);
-                } else {
-                    processRoutingRule(location.deviceId(), location.port(), hostMac,
-                                       hostVlanId, ip, true);
-                }
-            });
-            Sets.difference(newIps, prevIps).forEach(ip -> {
-                if (isDoubleTaggedHost(host)) {
-                    processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
-                                                   host.innerVlan(), hostVlanId, hostTpid, ip, false);
-                } else {
-                    processRoutingRule(location.deviceId(), location.port(), hostMac,
-                                       hostVlanId, ip, false);
-                }
-            });
-        });
-
-        // Use the pair link temporarily before the second location of a dual-homed host shows up.
-        // This do not affect single-homed hosts since the flow will be blocked in
-        // processBridgingRule or processRoutingRule due to VLAN or IP mismatch respectively
-        locations.forEach(location ->
-            srManager.getPairDeviceId(location.deviceId()).ifPresent(pairDeviceId -> {
-                if (locations.stream().noneMatch(l -> l.deviceId().equals(pairDeviceId))) {
-                    Set<IpAddress> ipsToAdd = Sets.difference(newIps, prevIps);
-                    Set<IpAddress> ipsToRemove = Sets.difference(prevIps, newIps);
-
-                    srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort -> {
-                        // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
-                        //       when the host is untagged
-                        VlanId vlanId = vlanForPairPort(hostVlanId, location);
-                        if (vlanId == null) {
-                            return;
-                        }
-
-                        ipsToRemove.forEach(ip ->
-                                processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, true)
-                        );
-                        ipsToAdd.forEach(ip ->
-                                processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, false)
-                        );
-
-                        if (srManager.activeProbing) {
-                            probe(host, location, pairDeviceId, pairRemotePort);
-                        }
-                    });
-                }
-            })
-        );
-    }
-
-    /**
-     * When a non-pair port comes up, probe each host on the pair device if
-     * (1) the host is tagged and the tagged vlan of current port contains host vlan; or
-     * (2) the host is untagged and the internal vlan is the same on the host port and current port.
-     *
-     * @param cp connect point
-     */
-    // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
-    void processPortUp(ConnectPoint cp) {
-        if (cp.port().equals(srManager.getPairLocalPort(cp.deviceId()).orElse(null))) {
-            return;
-        }
-        if (srManager.activeProbing) {
-            srManager.getPairDeviceId(cp.deviceId())
-                    .ifPresent(pairDeviceId -> srManager.hostService.getConnectedHosts(pairDeviceId).forEach(
-                            host -> hostWorkers.execute(() -> probingIfNecessary(host, pairDeviceId, cp),
-                                                        host.id().hashCode())));
-        }
-    }
-
-    // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
-    private void probingIfNecessary(Host host, DeviceId pairDeviceId, ConnectPoint cp) {
-        if (isHostInVlanOfPort(host, pairDeviceId, cp)) {
-            srManager.probingService.probeHost(host, cp, ProbeMode.DISCOVER);
-        }
-    }
-
-    /**
-     * Checks if given host located on given device id matches VLAN config of current port.
-     *
-     * @param host host to check
-     * @param deviceId device id to check
-     * @param cp current connect point
-     * @return true if the host located at deviceId matches the VLAN config on cp
-     */
-    private boolean isHostInVlanOfPort(Host host, DeviceId deviceId, ConnectPoint cp) {
-        VlanId internalVlan = srManager.getInternalVlanId(cp);
-        Set<VlanId> taggedVlan = srManager.interfaceService.getTaggedVlanId(cp);
-
-        return taggedVlan.contains(host.vlan()) ||
-                (internalVlan != null && effectiveLocations(host).stream()
-                        .filter(l -> l.deviceId().equals(deviceId))
-                        .map(srManager::getInternalVlanId)
-                        .anyMatch(internalVlan::equals));
-    }
-
-    /**
-     * Send a probe on all locations with the same VLAN on pair device, excluding pair port.
-     *
-     * @param host host to probe
-     * @param location newly discovered host location
-     * @param pairDeviceId pair device id
-     * @param pairRemotePort pair remote port
-     */
-    // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
-    private void probe(Host host, ConnectPoint location, DeviceId pairDeviceId, PortNumber pairRemotePort) {
-        //Check if the host still exists in the host store
-        if (hostService.getHost(host.id()) == null) {
-            log.debug("Host entry for host {} no more present. Aborting hostprobe discover for this host", host.id());
-            return;
-        }
-
-        VlanId vlanToProbe = host.vlan().equals(VlanId.NONE) ?
-                srManager.getInternalVlanId(location) : host.vlan();
-        if (srManager.symmetricProbing) {
-            srManager.interfaceService.getInterfaces().stream()
-                    .filter(i -> i.vlanTagged().contains(vlanToProbe) ||
-                            i.vlanUntagged().equals(vlanToProbe) ||
-                            i.vlanNative().equals(vlanToProbe))
-                    .filter(i -> i.connectPoint().deviceId().equals(pairDeviceId))
-                    .filter(i -> i.connectPoint().port().equals(location.port()))
-                    .forEach(i -> {
-                        log.debug("Probing host {} on pair device {}", host.id(), i.connectPoint());
-                        srManager.probingService.probeHost(host, i.connectPoint(), ProbeMode.DISCOVER);
-                    });
-        } else {
-            srManager.interfaceService.getInterfaces().stream()
-                    .filter(i -> i.vlanTagged().contains(vlanToProbe) ||
-                            i.vlanUntagged().equals(vlanToProbe) ||
-                            i.vlanNative().equals(vlanToProbe))
-                    .filter(i -> i.connectPoint().deviceId().equals(pairDeviceId))
-                    .filter(i -> !i.connectPoint().port().equals(pairRemotePort))
-                    .forEach(i -> {
-                        log.debug("Probing host {} on pair device {}", host.id(), i.connectPoint());
-                        srManager.probingService.probeHost(host, i.connectPoint(), ProbeMode.DISCOVER);
-                    });
-        }
-    }
-
-    /**
-     * Populates or revokes a bridging rule on given deviceId that matches given mac,
-     * given vlan and output to given port.
-     *
-     * @param deviceId device ID
-     * @param port port
-     * @param mac mac address
-     * @param vlanId VLAN ID
-     * @param revoke true to revoke the rule; false to populate
-     * @return future that includes the flow objective if succeeded, null if otherwise
-     */
-    private CompletableFuture<Objective> processBridgingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
-                                     VlanId vlanId, boolean revoke) {
-        log.info("{} bridging entry for host {}/{} at {}:{}", revoke ? "Revoking" : "Populating",
-                mac, vlanId, deviceId, port);
-
-        if (!revoke) {
-            return srManager.defaultRoutingHandler.populateBridging(deviceId, port, mac, vlanId);
-        } else {
-            return srManager.defaultRoutingHandler.revokeBridging(deviceId, port, mac, vlanId);
-        }
-    }
-
-    /**
-     * Populate or revoke a routing rule on given deviceId that matches given ip,
-     * set destination mac to given mac, set vlan to given vlan and output to given port.
-     *
-     * @param deviceId device ID
-     * @param port port
-     * @param mac mac address
-     * @param vlanId VLAN ID
-     * @param ip IP address
-     * @param revoke true to revoke the rule; false to populate
-     * @return future that includes the flow objective if succeeded, null if otherwise
-     */
-    private CompletableFuture<Objective> processRoutingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
-                                    VlanId vlanId, IpAddress ip, boolean revoke) {
-        ConnectPoint location = new ConnectPoint(deviceId, port);
-        if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
-            log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
-            return CompletableFuture.completedFuture(null);
-        }
-
-        log.info("{} routing rule for {} at {}", revoke ? "Revoking" : "Populating", ip, location);
-        if (revoke) {
-            return srManager.defaultRoutingHandler.revokeRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port, true);
-        } else {
-            return srManager.defaultRoutingHandler.populateRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port, true);
-        }
-    }
-
-    /**
-     * Populate or revoke a routing rule and egress rules on given deviceId that matches given IP,
-     * to set destination mac to given mac, set inner vlan and outer vlan to given vlans,
-     * set outer TPID, and output to given port.
-     *
-     * @param deviceId  device ID
-     * @param port      port
-     * @param mac       mac address
-     * @param innerVlan inner VLAN ID
-     * @param outerVlan outer VLAN ID
-     * @param outerTpid outer TPID
-     * @param ip        IP address
-     * @param revoke    true to revoke the rule; false to populate
-     */
-    private void processDoubleTaggedRoutingRule(DeviceId deviceId, PortNumber port,
-                                                MacAddress mac, VlanId innerVlan,
-                                                VlanId outerVlan, EthType outerTpid,
-                                                IpAddress ip, boolean revoke) {
-        if (!srManager.routeDoubleTaggedHosts) {
-            log.debug("Routing for double tagged host is disabled. Ignore {}/{}/{}", mac, outerVlan, innerVlan);
-            return;
-        }
-
-        ConnectPoint location = new ConnectPoint(deviceId, port);
-        if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
-            log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
-            return;
-        }
-        log.info("{} routing rule for double-tagged host {} at {}",
-                 revoke ? "Revoking" : "Populating", ip, location);
-        if (revoke) {
-            srManager.defaultRoutingHandler.revokeDoubleTaggedRoute(
-                    deviceId, ip.toIpPrefix(), mac, innerVlan, outerVlan, outerTpid, port);
-        } else {
-            srManager.defaultRoutingHandler.populateDoubleTaggedRoute(
-                    deviceId, ip.toIpPrefix(), mac, innerVlan, outerVlan, outerTpid, port);
-        }
-    }
-
-    void populateAllDoubleTaggedHost() {
-        log.info("Enabling routing for all double tagged hosts");
-        Sets.newHashSet(srManager.hostService.getHosts()).stream().filter(this::isDoubleTaggedHost)
-                .forEach(h -> effectiveLocations(h).forEach(l ->
-                    h.ipAddresses().forEach(i ->
-                        processDoubleTaggedRoutingRule(l.deviceId(), l.port(), h.mac(), h.innerVlan(),
-                                h.vlan(), h.tpid(), i, false)
-                    )
-            )
-        );
-    }
-
-    void revokeAllDoubleTaggedHost() {
-        log.info("Disabling routing for all double tagged hosts");
-        Sets.newHashSet(srManager.hostService.getHosts()).stream().filter(this::isDoubleTaggedHost)
-                .forEach(h -> effectiveLocations(h).forEach(l ->
-                    h.ipAddresses().forEach(i ->
-                        processDoubleTaggedRoutingRule(l.deviceId(), l.port(), h.mac(), h.innerVlan(),
-                            h.vlan(), h.tpid(), i, true)
-                    )
-            )
-        );
-    }
-
-    /**
-     * Returns VLAN ID to be used to program redirection flow on pair port.
-     *
-     * @param hostVlanId host VLAN ID
-     * @param location host location
-     * @return VLAN ID to be used; Or null if host VLAN does not match the interface config
-     */
-    VlanId vlanForPairPort(VlanId hostVlanId, ConnectPoint location) {
-        VlanId internalVlan = srManager.getInternalVlanId(location);
-        Set<VlanId> taggedVlan = srManager.interfaceService.getTaggedVlanId(location);
-
-        if (!hostVlanId.equals(VlanId.NONE) && taggedVlan.contains(hostVlanId)) {
-            return hostVlanId;
-        } else if (hostVlanId.equals(VlanId.NONE) && internalVlan != null) {
-            return internalVlan;
-        } else {
-            log.warn("VLAN mismatch. hostVlan={}, location={}, internalVlan={}, taggedVlan={}",
-                    hostVlanId, location, internalVlan, taggedVlan);
-            return null;
-        }
-    }
-
-    /**
-     * Update forwarding objective for unicast bridging and unicast routing.
-     * Also check the validity of updated interface configuration on VLAN.
-     *
-     * @param deviceId device ID that host attaches to
-     * @param portNum port number that host attaches to
-     * @param vlanId Vlan ID configured on the switch port
-     * @param popVlan true to pop Vlan tag at TrafficTreatment, false otherwise
-     * @param install true to populate the objective, false to revoke
-     */
-    // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
-    void processIntfVlanUpdatedEvent(DeviceId deviceId, PortNumber portNum, VlanId vlanId,
-                                     boolean popVlan, boolean install) {
-        ConnectPoint connectPoint = new ConnectPoint(deviceId, portNum);
-        Set<Host> hosts = hostService.getConnectedHosts(connectPoint);
-
-        if (hosts == null || hosts.size() == 0) {
-            log.debug("processIntfVlanUpdatedEvent: No hosts connected to {}", connectPoint);
-            return;
-        }
-
-        hosts.forEach(host -> hostWorkers.execute(() -> processIntfVlanUpdatedEventInternal(
-                host, deviceId, portNum, vlanId, popVlan, install), host.id().hashCode()));
-    }
-
-    private void processIntfVlanUpdatedEventInternal(Host host, DeviceId deviceId, PortNumber portNum,
-                                                     VlanId vlanId, boolean popVlan, boolean install) {
-        MacAddress mac = host.mac();
-        VlanId hostVlanId = host.vlan();
-
-        if (!install) {
-            // Do not check the host validity. Just remove all rules corresponding to the vlan id
-            // Revoke forwarding objective for bridging to the host
-            srManager.defaultRoutingHandler.updateBridging(deviceId, portNum, mac, vlanId, popVlan, false);
-
-            // Revoke forwarding objective and corresponding simple Next objective
-            // for each Host and IP address connected to given port
-            host.ipAddresses().forEach(ipAddress ->
-                srManager.routingRulePopulator.updateFwdObj(deviceId, portNum, ipAddress.toIpPrefix(),
-                                                            mac, vlanId, popVlan, false)
-            );
-        } else {
-            // Check whether the host vlan is valid for new interface configuration
-            if ((!popVlan && hostVlanId.equals(vlanId)) ||
-                    (popVlan && hostVlanId.equals(VlanId.NONE))) {
-                srManager.defaultRoutingHandler.updateBridging(deviceId, portNum, mac, vlanId, popVlan, true);
-                // Update Forwarding objective and corresponding simple Next objective
-                // for each Host and IP address connected to given port
-                host.ipAddresses().forEach(ipAddress ->
-                    srManager.routingRulePopulator.updateFwdObj(deviceId, portNum, ipAddress.toIpPrefix(),
-                                                                mac, vlanId, popVlan, true)
-                );
-            }
-        }
-    }
-
-    /**
-     * Populate or revoke routing rule for each host, according to the updated
-     * subnet configuration on the interface.
-     * @param cp connect point of the updated interface
-     * @param ipPrefixSet IP Prefixes added or removed
-     * @param install true if IP Prefixes added, false otherwise
-     */
-    // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
-    void processIntfIpUpdatedEvent(ConnectPoint cp, Set<IpPrefix> ipPrefixSet, boolean install) {
-        Set<Host> hosts = hostService.getConnectedHosts(cp);
-
-        if (hosts == null || hosts.size() == 0) {
-            log.debug("processIntfIpUpdatedEvent: No hosts connected to {}", cp);
-            return;
-        }
-
-        // Check whether the host IP address is in the interface's subnet
-        hosts.forEach(host -> hostWorkers.execute(() -> processIntfIpUpdatedEventInternal(
-                host, cp, ipPrefixSet, install)));
-    }
-
-    private void processIntfIpUpdatedEventInternal(Host host, ConnectPoint cp, Set<IpPrefix> ipPrefixSet,
-                                                   boolean install) {
-        host.ipAddresses().forEach(hostIpAddress -> {
-            ipPrefixSet.forEach(ipPrefix -> {
-                if (install && ipPrefix.contains(hostIpAddress)) {
-                    srManager.defaultRoutingHandler.populateRoute(cp.deviceId(), hostIpAddress.toIpPrefix(),
-                                                                  host.mac(), host.vlan(), cp.port(), true);
-                } else if (!install && ipPrefix.contains(hostIpAddress)) {
-                    srManager.defaultRoutingHandler.revokeRoute(cp.deviceId(), hostIpAddress.toIpPrefix(),
-                                                                host.mac(), host.vlan(), cp.port(), true);
-                }
-            });
-        });
-    }
-
-    /**
-     * Returns the set of portnumbers on the given device that are part of the
-     * locations for dual-homed hosts.
-     *
-     * @param deviceId the given deviceId
-     * @return set of port numbers on given device that are dual-homed host
-     *         locations. May be empty if no dual homed hosts are connected to
-     *         the given device
-     */
-    Set<PortNumber> getDualHomedHostPorts(DeviceId deviceId) {
-        Set<PortNumber> dualHomedLocations = new HashSet<>();
-        srManager.hostService.getConnectedHosts(deviceId).stream()
-            .filter(host -> effectiveLocations(host).size() == 2)
-            .forEach(host -> effectiveLocations(host).stream()
-                     .filter(loc -> loc.deviceId().equals(deviceId))
-                        .forEach(loc -> dualHomedLocations.add(loc.port())));
-        return dualHomedLocations;
-    }
-
-    /**
-     * Checks if the given host is double-tagged or not.
-     *
-     * @param host host to check
-     * @return true if it is double-tagged, false otherwise
-     */
-    private boolean isDoubleTaggedHost(Host host) {
-        return !host.innerVlan().equals(VlanId.NONE);
-    }
-
-    /**
-     * Returns effective locations of given host.
-     *
-     * @param host host to check
-     * @return auxLocations of the host if exists, or locations of the host otherwise.
-     */
-    Set<HostLocation> effectiveLocations(Host host) {
-        return (host.auxLocations() != null) ? host.auxLocations() : host.locations();
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
deleted file mode 100644
index fc3dd17..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * 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 org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MPLS;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ndp.NeighborSolicitation;
-import org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.neighbour.NeighbourMessageType;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Handler of ICMP packets that responses or forwards ICMP packets that
- * are sent to the controller.
- */
-public class IcmpHandler extends SegmentRoutingNeighbourHandler {
-
-    private static Logger log = LoggerFactory.getLogger(IcmpHandler.class);
-
-    /**
-     * Creates an IcmpHandler object.
-     *
-     * @param srManager SegmentRoutingManager object
-     */
-    public IcmpHandler(SegmentRoutingManager srManager) {
-        super(srManager);
-    }
-
-    /**
-     * Utility function to send packet out.
-     *
-     * @param outport the output port
-     * @param payload the packet to send
-     * @param destSid the segment id of the dest device
-     * @param destIpAddress the destination ip address
-     * @param allowedHops the hop limit/ttl
-     */
-    private void sendPacketOut(ConnectPoint outport,
-                               Ethernet payload,
-                               int destSid,
-                               IpAddress destIpAddress,
-                               byte allowedHops) {
-        int origSid;
-        try {
-            if (destIpAddress.isIp4()) {
-                origSid = config.getIPv4SegmentId(outport.deviceId());
-            } else {
-                origSid = config.getIPv6SegmentId(outport.deviceId());
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting sendPacketOut");
-            return;
-        }
-
-        if (destSid == -1 || origSid == destSid ||
-                srManager.interfaceService.isConfigured(outport)) {
-            TrafficTreatment treatment = DefaultTrafficTreatment.builder().
-                    setOutput(outport.port()).build();
-            OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
-                                                              treatment, ByteBuffer.wrap(payload.serialize()));
-            log.trace("Sending packet {} to {}", payload, outport);
-            srManager.packetService.emit(packet);
-        } else {
-            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                    .setOutput(outport.port())
-                    .build();
-
-            payload.setEtherType(Ethernet.MPLS_UNICAST);
-            MPLS mplsPkt = new MPLS();
-            mplsPkt.setLabel(destSid);
-            mplsPkt.setTtl(allowedHops);
-            mplsPkt.setPayload(payload.getPayload());
-            payload.setPayload(mplsPkt);
-            OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
-                                                              treatment, ByteBuffer.wrap(payload.serialize()));
-            log.trace("Sending packet {} to {}", payload, outport);
-            srManager.packetService.emit(packet);
-        }
-    }
-
-    private IpAddress selectRouterIpAddress(IpAddress destIpAddress, ConnectPoint outPort,
-                                            Set<ConnectPoint> connectPoints) {
-        IpAddress routerIpAddress;
-        // Let's get first the online connect points
-        Set<ConnectPoint> onlineCps =  connectPoints.stream()
-                .filter(connectPoint -> srManager.deviceService.isAvailable(connectPoint.deviceId()))
-                .collect(Collectors.toSet());
-        // Check if ping is local
-        if (onlineCps.contains(outPort)) {
-            routerIpAddress = config.getRouterIpAddress(destIpAddress, outPort.deviceId());
-            log.trace("Local ping received from {} - send to {}", destIpAddress, routerIpAddress);
-            return routerIpAddress;
-        }
-        // Check if it comes from a remote device. Loopbacks are sorted comparing byte by byte
-        // FIXME if we lose both links from the chosen leaf to spine - ping will fail
-        routerIpAddress = onlineCps.stream()
-                .filter(onlineCp -> !onlineCp.deviceId().equals(outPort.deviceId()))
-                .map(selectedCp -> config.getRouterIpAddress(destIpAddress, selectedCp.deviceId()))
-                .filter(Objects::nonNull)
-                .sorted()
-                .findFirst().orElse(null);
-        if (routerIpAddress != null) {
-            log.trace("Remote ping received from {} - send to {}", destIpAddress, routerIpAddress);
-        } else {
-            log.warn("Not found a valid loopback for ping coming from {} - {}", destIpAddress, outPort);
-        }
-        return routerIpAddress;
-    }
-
-    private Ip4Address selectRouterIp4Address(IpAddress destIpAddress, ConnectPoint outPort,
-                                              Set<ConnectPoint> connectPoints) {
-        IpAddress routerIpAddress = selectRouterIpAddress(destIpAddress, outPort, connectPoints);
-        return routerIpAddress != null ? routerIpAddress.getIp4Address() : null;
-    }
-
-    private Ip6Address selectRouterIp6Address(IpAddress destIpAddress, ConnectPoint outPort,
-                                              Set<ConnectPoint> connectPoints) {
-        IpAddress routerIpAddress = selectRouterIpAddress(destIpAddress, outPort, connectPoints);
-        return routerIpAddress != null ? routerIpAddress.getIp6Address() : null;
-    }
-
-    //////////////////////////////////////
-    //     ICMP Echo/Reply Protocol     //
-    //////////////////////////////////////
-
-    /**
-     * Process incoming ICMP packet.
-     * If it is an ICMP request to router, then sends an ICMP response.
-     * Otherwise ignore the packet.
-     *
-     * @param eth inbound ICMP packet
-     * @param inPort the input port
-     */
-    public void processIcmp(Ethernet eth, ConnectPoint inPort) {
-        DeviceId deviceId = inPort.deviceId();
-        IPv4 ipv4Packet = (IPv4) eth.getPayload();
-        ICMP icmp = (ICMP) ipv4Packet.getPayload();
-        Ip4Address destinationAddress = Ip4Address.valueOf(ipv4Packet.getDestinationAddress());
-        Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
-        IpAddress routerIp;
-
-        // Only proceed with echo request
-        if (icmp.getIcmpType() != ICMP.TYPE_ECHO_REQUEST) {
-            return;
-        }
-
-        try {
-            routerIp = config.getRouterIpv4(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting processPacketIn.");
-            return;
-        }
-
-        // Get pair ip - if it exists
-        IpAddress pairRouterIp;
-        try {
-            DeviceId pairDeviceId = config.getPairDeviceId(deviceId);
-            pairRouterIp = pairDeviceId != null ? config.getRouterIpv4(pairDeviceId) : null;
-        } catch (DeviceConfigNotFoundException e) {
-            pairRouterIp = null;
-        }
-
-        // ICMP to the router IP or gateway IP
-        if (destinationAddress.equals(routerIp.getIp4Address()) ||
-                (pairRouterIp != null && destinationAddress.equals(pairRouterIp.getIp4Address())) ||
-                gatewayIpAddresses.contains(destinationAddress)) {
-            sendIcmpResponse(eth, inPort);
-        } else {
-            log.trace("Ignore ICMP that targets for {}", destinationAddress);
-        }
-    }
-
-    /**
-     * Sends an ICMP reply message.
-     *
-     * @param icmpRequest the original ICMP request
-     * @param outport the output port where the ICMP reply should be sent to
-     */
-    private void sendIcmpResponse(Ethernet icmpRequest, ConnectPoint outport) {
-        Ethernet icmpReplyEth = ICMP.buildIcmpReply(icmpRequest);
-        IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
-        IPv4 icmpReplyIpv4 = (IPv4) icmpReplyEth.getPayload();
-        Ip4Address destIpAddress = Ip4Address.valueOf(icmpRequestIpv4.getSourceAddress());
-
-        // Get the available connect points
-        Set<ConnectPoint> destConnectPoints = config.getConnectPointsForASubnetHost(destIpAddress);
-        // Select a router
-        Ip4Address destRouterAddress = selectRouterIp4Address(destIpAddress, outport, destConnectPoints);
-
-        // Note: Source IP of the ICMP request doesn't belong to any configured subnet.
-        //       The source might be an indirectly attached host (e.g. behind a router)
-        //       Lookup the route store for the nexthop instead.
-        if (destRouterAddress == null) {
-            Optional<DeviceId> deviceId = srManager.routeService
-                    .longestPrefixLookup(destIpAddress).map(srManager::nextHopLocations)
-                    .flatMap(locations -> locations.stream().findFirst())
-                    .map(ConnectPoint::deviceId);
-            if (deviceId.isPresent()) {
-                try {
-                    destRouterAddress = config.getRouterIpv4(deviceId.get());
-                } catch (DeviceConfigNotFoundException e) {
-                    log.warn("Device config for {} not found. Abort ICMP processing", deviceId);
-                    return;
-                }
-            }
-        }
-
-        int destSid = config.getIPv4SegmentId(destRouterAddress);
-        if (destSid < 0) {
-            log.warn("Failed to lookup SID of the switch that {} attaches to. " +
-                    "Unable to process ICMP request.", destIpAddress);
-            return;
-        }
-        sendPacketOut(outport, icmpReplyEth, destSid, destIpAddress, icmpReplyIpv4.getTtl());
-    }
-
-    ///////////////////////////////////////////
-    //      ICMPv6 Echo/Reply Protocol       //
-    ///////////////////////////////////////////
-
-    /**
-     * Process incoming ICMPv6 packet.
-     * If it is an ICMPv6 request to router, then sends an ICMPv6 response.
-     * Otherwise ignore the packet.
-     *
-     * @param eth the incoming ICMPv6 packet
-     * @param inPort the input port
-     */
-    public void processIcmpv6(Ethernet eth, ConnectPoint inPort) {
-        DeviceId deviceId = inPort.deviceId();
-        IPv6 ipv6Packet = (IPv6) eth.getPayload();
-        ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
-        Ip6Address destinationAddress = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
-        Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
-        IpAddress routerIp;
-
-        // Only proceed with echo request
-        if (icmp6.getIcmpType() != ICMP6.ECHO_REQUEST) {
-            return;
-        }
-
-        try {
-            routerIp = config.getRouterIpv6(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting processPacketIn.");
-            return;
-        }
-
-        // Get pair ip - if it exists
-        IpAddress pairRouterIp;
-        try {
-            DeviceId pairDeviceId = config.getPairDeviceId(deviceId);
-            pairRouterIp = pairDeviceId != null ? config.getRouterIpv6(pairDeviceId) : null;
-        } catch (DeviceConfigNotFoundException e) {
-            pairRouterIp = null;
-        }
-
-        Optional<Ip6Address> linkLocalIp = getLinkLocalIp(inPort);
-        // Ensure ICMP to the router IP, EUI-64 link-local IP, or gateway IP
-        if (destinationAddress.equals(routerIp.getIp6Address()) ||
-                (linkLocalIp.isPresent() && destinationAddress.equals(linkLocalIp.get())) ||
-                (pairRouterIp != null && destinationAddress.equals(pairRouterIp.getIp6Address())) ||
-                gatewayIpAddresses.contains(destinationAddress)) {
-            sendIcmpv6Response(eth, inPort);
-        } else {
-            log.trace("Ignore ICMPv6 that targets for {}", destinationAddress);
-        }
-    }
-
-    /**
-     * Sends an ICMPv6 reply message.
-     *
-     * @param ethRequest the original ICMP request
-     * @param outport the output port where the ICMP reply should be sent to
-     */
-    private void sendIcmpv6Response(Ethernet ethRequest, ConnectPoint outport) {
-        int destSid = -1;
-        Ethernet ethReply = ICMP6.buildIcmp6Reply(ethRequest);
-        IPv6 icmpRequestIpv6 = (IPv6) ethRequest.getPayload();
-        IPv6 icmpReplyIpv6 = (IPv6) ethRequest.getPayload();
-        // Source IP of the echo "reply"
-        Ip6Address srcIpAddress = Ip6Address.valueOf(icmpRequestIpv6.getDestinationAddress());
-        // Destination IP of the echo "reply"
-        Ip6Address destIpAddress = Ip6Address.valueOf(icmpRequestIpv6.getSourceAddress());
-        Optional<Ip6Address> linkLocalIp = getLinkLocalIp(outport);
-
-        // Fast path if the echo request targets the link-local address of switch interface
-        if (linkLocalIp.isPresent() && srcIpAddress.equals(linkLocalIp.get())) {
-            sendPacketOut(outport, ethReply, destSid, destIpAddress, icmpReplyIpv6.getHopLimit());
-            return;
-        }
-
-        // Get the available connect points
-        Set<ConnectPoint> destConnectPoints = config.getConnectPointsForASubnetHost(destIpAddress);
-        // Select a router
-        Ip6Address destRouterAddress = selectRouterIp6Address(destIpAddress, outport, destConnectPoints);
-
-        // Note: Source IP of the ICMP request doesn't belong to any configured subnet.
-        //       The source might be an indirect host behind a router.
-        //       Lookup the route store for the nexthop instead.
-        if (destRouterAddress == null) {
-            Optional<DeviceId> deviceId = srManager.routeService
-                    .longestPrefixLookup(destIpAddress).map(srManager::nextHopLocations)
-                    .flatMap(locations -> locations.stream().findFirst())
-                    .map(ConnectPoint::deviceId);
-            if (deviceId.isPresent()) {
-                try {
-                    destRouterAddress = config.getRouterIpv6(deviceId.get());
-                } catch (DeviceConfigNotFoundException e) {
-                    log.warn("Device config for {} not found. Abort ICMPv6 processing", deviceId);
-                    return;
-                }
-            }
-        }
-
-        destSid = config.getIPv6SegmentId(destRouterAddress);
-        if (destSid < 0) {
-            log.warn("Failed to lookup SID of the switch that {} attaches to. " +
-                    "Unable to process ICMPv6 request.", destIpAddress);
-            return;
-        }
-        sendPacketOut(outport, ethReply, destSid, destIpAddress, icmpReplyIpv6.getHopLimit());
-    }
-
-    ///////////////////////////////////////////
-    //  ICMPv6 Neighbour Discovery Protocol  //
-    ///////////////////////////////////////////
-
-    /**
-     * Process incoming NDP packet.
-     *
-     * If it is an NDP request for the router or for the gateway, then sends a NDP reply.
-     * If it is an NDP request to unknown host flood in the subnet.
-     * If it is an NDP packet to known host forward the packet to the host.
-     *
-     * FIXME If the NDP packets use link local addresses we fail.
-     *
-     * @param pkt inbound packet
-     * @param hostService the host service
-     */
-    public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {
-        // First we validate the ndp packet
-        SegmentRoutingAppConfig appConfig = srManager.cfgService
-                .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
-        if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
-            // Ignore NDP packets come from suppressed ports
-            pkt.drop();
-            return;
-        }
-
-        if (pkt.type() == NeighbourMessageType.REQUEST) {
-            handleNdpRequest(pkt, hostService);
-        } else {
-            handleNdpReply(pkt, hostService);
-        }
-
-    }
-
-    /**
-     * Helper method to handle the ndp requests.
-     * @param pkt the ndp packet request and context information
-     * @param hostService the host service
-     */
-    private void handleNdpRequest(NeighbourMessageContext pkt, HostService hostService) {
-        // ND request for the gateway. We have to reply on behalf of the gateway.
-        if (isNdpForGateway(pkt)) {
-            log.trace("Sending NDP reply on behalf of gateway IP for pkt: {}", pkt.target());
-            MacAddress routerMac = config.getRouterMacForAGatewayIp(pkt.target());
-            if (routerMac == null) {
-                log.warn("Router MAC of {} is not configured. Cannot handle NDP request from {}",
-                        pkt.inPort().deviceId(), pkt.sender());
-                return;
-            }
-            sendResponse(pkt, routerMac, hostService, true);
-        } else {
-
-            // Process NDP targets towards EUI-64 address.
-            try {
-                DeviceId deviceId = pkt.inPort().deviceId();
-
-                Optional<Ip6Address> linkLocalIp = getLinkLocalIp(pkt.inPort());
-                if (linkLocalIp.isPresent() && pkt.target().equals(linkLocalIp.get())) {
-                    MacAddress routerMac = config.getDeviceMac(deviceId);
-                    sendResponse(pkt, routerMac, hostService, true);
-                }
-            } catch (DeviceConfigNotFoundException e) {
-                log.warn(e.getMessage() + " Unable to handle NDP packet to {}. Aborting.", pkt.target());
-                return;
-            }
-
-            // NOTE: Ignore NDP packets except those target for the router
-            //       We will reconsider enabling this when we have host learning support
-            /*
-            // ND request for an host. We do a search by Ip.
-            Set<Host> hosts = hostService.getHostsByIp(pkt.target());
-            // Possible misconfiguration ? In future this case
-            // should be handled we can have same hosts in different VLANs.
-            if (hosts.size() > 1) {
-                log.warn("More than one host with IP {}", pkt.target());
-            }
-            Host targetHost = hosts.stream().findFirst().orElse(null);
-            // If we know the host forward to its attachment point.
-            if (targetHost != null) {
-                log.debug("Forward NDP request to the target host");
-                pkt.forward(targetHost.location());
-            } else {
-                // Flood otherwise.
-                log.debug("Flood NDP request to the target subnet");
-                flood(pkt);
-            }
-            */
-        }
-    }
-
-    /**
-     * Helper method to handle the ndp replies.
-     *
-     * @param pkt the ndp packet reply and context information
-     * @param hostService the host service
-     */
-    private void handleNdpReply(NeighbourMessageContext pkt, HostService hostService) {
-        if (isNdpForGateway(pkt)) {
-            log.debug("Forwarding all the ip packets we stored");
-            Ip6Address hostIpAddress = pkt.sender().getIp6Address();
-            srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
-        } else {
-            // NOTE: Ignore NDP packets except those target for the router
-            //       We will reconsider enabling this when we have host learning support
-            /*
-            HostId hostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
-            Host targetHost = hostService.getHost(hostId);
-            if (targetHost != null) {
-                log.debug("Forwarding the reply to the host");
-                pkt.forward(targetHost.location());
-            } else {
-                // We don't have to flood towards spine facing ports.
-                if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
-                    return;
-                }
-                log.debug("Flooding the reply to the subnet");
-                flood(pkt);
-            }
-            */
-        }
-    }
-
-    /**
-     * Utility to verify if the ND are for the gateway.
-     *
-     * @param pkt the ndp packet
-     * @return true if the ndp is for the gateway. False otherwise
-     */
-    private boolean isNdpForGateway(NeighbourMessageContext pkt) {
-        DeviceId deviceId = pkt.inPort().deviceId();
-        Set<IpAddress> gatewayIpAddresses = null;
-
-        try {
-            if (pkt.target().equals(config.getRouterIpv6(deviceId))) {
-                return true;
-            }
-            gatewayIpAddresses = config.getPortIPs(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting check for router IP in processing ndp");
-            return false;
-        }
-        return gatewayIpAddresses != null && gatewayIpAddresses.stream()
-                .filter(IpAddress::isIp6)
-                .anyMatch(gatewayIp -> gatewayIp.equals(pkt.target()) ||
-                        Arrays.equals(IPv6.getSolicitNodeAddress(gatewayIp.toOctets()),
-                                pkt.target().toOctets()));
-    }
-
-    /**
-     * Sends a NDP request for the target IP address to all ports except in-port.
-     *
-     * @param deviceId Switch device ID
-     * @param targetAddress target IP address for ARP
-     * @param inPort in-port
-     */
-    public void sendNdpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
-        byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
-        byte[] senderIpAddress = new byte[Ip6Address.BYTE_LENGTH];
-        // Retrieves device info.
-        if (!getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress)) {
-            log.warn("Aborting sendNdpRequest, we cannot get all the information needed");
-            return;
-        }
-        // We have to compute the dst mac address and dst ip address.
-        byte[] dstIp = IPv6.getSolicitNodeAddress(targetAddress.toOctets());
-        byte[] dstMac = IPv6.getMCastMacAddress(dstIp);
-        // Creates the request.
-        Ethernet ndpRequest = NeighborSolicitation.buildNdpSolicit(
-                targetAddress.getIp6Address(),
-                Ip6Address.valueOf(senderIpAddress),
-                Ip6Address.valueOf(dstIp),
-                MacAddress.valueOf(senderMacAddress),
-                MacAddress.valueOf(dstMac),
-                VlanId.NONE
-        );
-        flood(ndpRequest, inPort, targetAddress);
-    }
-
-    /**
-     * Returns link-local IP of given connect point.
-     *
-     * @param cp connect point
-     * @return optional link-local IP
-     */
-    private Optional<Ip6Address> getLinkLocalIp(ConnectPoint cp) {
-        return srManager.interfaceService.getInterfacesByPort(cp)
-                .stream()
-                .map(Interface::mac)
-                .map(MacAddress::toBytes)
-                .map(IPv6::getLinkLocalAddress)
-                .map(Ip6Address::valueOf)
-                .findFirst();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IpHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IpHandler.java
deleted file mode 100644
index c445ac4..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IpHandler.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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 org.onlab.packet.Ethernet;
-import org.onlab.packet.IP;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onlab.packet.IpAddress.Version.INET6;
-
-/**
- * Handler of IP packets that forwards IP packets that are sent to the controller,
- * except the ICMP packets which are processed by @link{IcmpHandler}.
- */
-public class IpHandler {
-
-    private static Logger log = LoggerFactory.getLogger(IpHandler.class);
-    private SegmentRoutingManager srManager;
-    private DeviceConfiguration config;
-    private ConcurrentHashMap<IpAddress, ConcurrentLinkedQueue<IP>> ipPacketQueue;
-
-    /**
-     * Creates an IpHandler object.
-     *
-     * @param srManager SegmentRoutingManager object
-     */
-    public IpHandler(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-        this.config = checkNotNull(srManager.deviceConfiguration);
-        ipPacketQueue = new ConcurrentHashMap<>();
-    }
-
-    /**
-     * Enqueues the packet using the destination address as key.
-     *
-     * @param ipPacket the ip packet to store
-     * @param destinationAddress the destination address
-     */
-    private void enqueuePacket(IP ipPacket, IpAddress destinationAddress) {
-
-        ipPacketQueue
-            .computeIfAbsent(destinationAddress, a -> new ConcurrentLinkedQueue<>())
-            .add(ipPacket);
-
-    }
-
-    /**
-     * Dequeues the packet using the destination address as key.
-     *
-     * @param ipPacket the ip packet to remove
-     * @param destinationAddress the destination address
-     */
-    public void dequeuePacket(IP ipPacket, IpAddress destinationAddress) {
-
-        if (ipPacketQueue.get(destinationAddress) == null) {
-            return;
-        }
-        ipPacketQueue.get(destinationAddress).remove(ipPacket);
-    }
-
-    /**
-     * Forwards the packet to a given host and deque the packet.
-     *
-     * @param deviceId the target device
-     * @param eth the packet to send
-     * @param dest the target host
-     */
-    private void forwardToHost(DeviceId deviceId, Ethernet eth, Host dest) {
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder().
-                setOutput(dest.location().port()).build();
-        OutboundPacket packet = new DefaultOutboundPacket(deviceId,
-                                                          treatment, ByteBuffer.wrap(eth.serialize()));
-        srManager.packetService.emit(packet);
-    }
-
-    //////////////////////
-    //  IPv4 Handling  //
-    ////////////////////
-
-    /**
-     * Processes incoming IP packets.
-     *
-     * If it is an IP packet for known host, then forward it to the host.
-     * If it is an IP packet for unknown host in subnet, then send an ARP request
-     * to the subnet.
-     *
-     * @param pkt incoming packet
-     * @param connectPoint the target device
-     */
-    public void processPacketIn(IPv4 pkt, ConnectPoint connectPoint) {
-
-        DeviceId deviceId = connectPoint.deviceId();
-        Ip4Address destinationAddress = Ip4Address.valueOf(pkt.getDestinationAddress());
-
-        // IP packet for know hosts
-        if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
-            forwardPackets(deviceId, destinationAddress);
-
-        // IP packet for unknown host in one of the configured subnets of the router
-        } else if (config.inSameSubnet(deviceId, destinationAddress)) {
-            srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, connectPoint);
-
-        // IP packets for unknown host
-        } else {
-            log.debug("IPv4 packet for unknown host {} which is not in the subnet",
-                    destinationAddress);
-            // Do nothing
-        }
-    }
-
-    /**
-     * Adds the IP packet to a buffer.
-     * The packets are forwarded to corresponding destination when the destination
-     * MAC address is known via ARP response.
-     *
-     * @param ipPacket IP packet to add to the buffer
-     */
-    public void addToPacketBuffer(IPv4 ipPacket) {
-
-        // Better not buffer TCP packets due to out-of-order packet transfer
-        if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) {
-            return;
-        }
-        IpAddress destIpAddress = IpAddress.valueOf(ipPacket.getDestinationAddress());
-        enqueuePacket(ipPacket, destIpAddress);
-    }
-
-    /**
-     * Forwards IP packets in the buffer to the destination IP address.
-     * It is called when the controller finds the destination MAC address
-     * via ARP responses.
-     *
-     * @param deviceId switch device ID
-     * @param destIpAddress destination IP address
-     */
-    public void forwardPackets(DeviceId deviceId, Ip4Address destIpAddress) {
-        if (ipPacketQueue.get(destIpAddress) == null) {
-            return;
-        }
-        for (IP ipPacket : ipPacketQueue.get(destIpAddress)) {
-            if (ipPacket.getVersion() == ((byte) 4)) {
-                IPv4 ipv4Packet = (IPv4) ipPacket;
-                Ip4Address destAddress = Ip4Address.valueOf(ipv4Packet.getDestinationAddress());
-                if (config.inSameSubnet(deviceId, destAddress)) {
-                    ipv4Packet.setTtl((byte) (ipv4Packet.getTtl() - 1));
-                    ipv4Packet.setChecksum((short) 0);
-                    for (Host dest : srManager.hostService.getHostsByIp(destIpAddress)) {
-                        Ethernet eth = new Ethernet();
-                        eth.setDestinationMACAddress(dest.mac());
-                        try {
-                            eth.setSourceMACAddress(config.getDeviceMac(deviceId));
-                        } catch (DeviceConfigNotFoundException e) {
-                            log.warn(e.getMessage()
-                                             + " Skipping forwardPackets for this destination.");
-                            continue;
-                        }
-                        eth.setEtherType(Ethernet.TYPE_IPV4);
-                        eth.setPayload(ipv4Packet);
-                        forwardToHost(deviceId, eth, dest);
-                        ipPacketQueue.get(destIpAddress).remove(ipPacket);
-                    }
-                    ipPacketQueue.get(destIpAddress).remove(ipPacket);
-                }
-            }
-        }
-    }
-
-    //////////////////////
-    //  IPv6 Handling  //
-    ////////////////////
-
-    /**
-     * Processes incoming IPv6 packets.
-     *
-     * If it is an IPv6 packet for known host, then forward it to the host.
-     * If it is an IPv6 packet for unknown host in subnet, then send an NDP request
-     * to the subnet.
-     *
-     * @param pkt incoming packet
-     * @param connectPoint the target device
-     */
-    public void processPacketIn(IPv6 pkt, ConnectPoint connectPoint) {
-
-        DeviceId deviceId = connectPoint.deviceId();
-        Ip6Address destinationAddress = Ip6Address.valueOf(pkt.getDestinationAddress());
-
-        // IPv6 packet for know hosts
-        if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
-            forwardPackets(deviceId, destinationAddress);
-
-            // IPv6 packet for unknown host in one of the configured subnets of the router
-        } else if (config.inSameSubnet(deviceId, destinationAddress)) {
-            srManager.icmpHandler.sendNdpRequest(deviceId, destinationAddress, connectPoint);
-
-            // IPv6 packets for unknown host
-        } else {
-            log.debug("IPv6 packet for unknown host {} which is not in the subnet",
-                      destinationAddress);
-        }
-    }
-
-    /**
-     * Adds the IPv6 packet to a buffer.
-     * The packets are forwarded to corresponding destination when the destination
-     * MAC address is known via NDP response.
-     *
-     * @param ipPacket IP packet to add to the buffer
-     */
-    public void addToPacketBuffer(IPv6 ipPacket) {
-
-        // Better not buffer TCP packets due to out-of-order packet transfer
-        if (ipPacket.getNextHeader() == IPv6.PROTOCOL_TCP) {
-            return;
-        }
-        IpAddress destIpAddress = IpAddress.valueOf(INET6, ipPacket.getDestinationAddress());
-        enqueuePacket(ipPacket, destIpAddress);
-    }
-
-    /**
-     * Forwards IP packets in the buffer to the destination IP address.
-     * It is called when the controller finds the destination MAC address
-     * via NDP replies.
-     *
-     * @param deviceId the target device
-     * @param destIpAddress the destination ip address
-     */
-    public void forwardPackets(DeviceId deviceId, Ip6Address destIpAddress) {
-        if (ipPacketQueue.get(destIpAddress) == null) {
-            return;
-        }
-        for (IP ipPacket : ipPacketQueue.get(destIpAddress)) {
-            if (ipPacket.getVersion() == ((byte) 6)) {
-                IPv6 ipv6Packet = (IPv6) ipPacket;
-                Ip6Address destAddress = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
-                if (config.inSameSubnet(deviceId, destAddress)) {
-                    ipv6Packet.setHopLimit((byte) (ipv6Packet.getHopLimit() - 1));
-                    for (Host dest : srManager.hostService.getHostsByIp(destIpAddress)) {
-                        Ethernet eth = new Ethernet();
-                        eth.setDestinationMACAddress(dest.mac());
-                        try {
-                            eth.setSourceMACAddress(config.getDeviceMac(deviceId));
-                        } catch (DeviceConfigNotFoundException e) {
-                            log.warn(e.getMessage()
-                                             + " Skipping forwardPackets for this destination.");
-                            continue;
-                        }
-                        eth.setEtherType(Ethernet.TYPE_IPV6);
-                        eth.setPayload(ipv6Packet);
-                        forwardToHost(deviceId, eth, dest);
-                        ipPacketQueue.get(destIpAddress).remove(ipPacket);
-                    }
-                    ipPacketQueue.get(destIpAddress).remove(ipPacket);
-                }
-            }
-            ipPacketQueue.get(destIpAddress).remove(ipPacket);
-        }
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
deleted file mode 100644
index 2193c95..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
+++ /dev/null
@@ -1,736 +0,0 @@
-/*
- * Copyright 2018-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 java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.onosproject.store.service.EventuallyConsistentMapBuilder;
-import org.onosproject.store.service.WallClockTimestamp;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
-
-
-public class LinkHandler {
-    private static final Logger log = LoggerFactory.getLogger(LinkHandler.class);
-    protected final SegmentRoutingManager srManager;
-
-    // Local store for all links seen and their present status, used for
-    // optimized routing. The existence of the link in the keys is enough to know
-    // if the link has been "seen-before" by this instance of the controller.
-    // The boolean value indicates if the link is currently up or not.
-    // Currently the optimized routing logic depends on "forgetting" a link
-    // when a switch goes down, but "remembering" it when only the link goes down.
-    private Map<Link, Boolean> seenLinks = new ConcurrentHashMap<>();
-    private Set<Link> seenBefore = Sets.newConcurrentHashSet();
-    private EventuallyConsistentMap<DeviceId, Set<PortNumber>> downedPortStore = null;
-
-    /**
-     * Constructs the LinkHandler.
-     *
-     * @param srManager Segment Routing manager
-     */
-    LinkHandler(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-        log.debug("Creating EC map downedportstore");
-        EventuallyConsistentMapBuilder<DeviceId, Set<PortNumber>> downedPortsMapBuilder
-                = srManager.storageService.eventuallyConsistentMapBuilder();
-        downedPortStore = downedPortsMapBuilder.withName("downedportstore")
-                .withSerializer(srManager.createSerializer())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-        log.trace("Current size {}", downedPortStore.size());
-    }
-
-    /**
-     * Constructs the LinkHandler for unit-testing.
-     *
-     * @param srManager SegmentRoutingManager
-     * @param linkService LinkService
-     */
-    LinkHandler(SegmentRoutingManager srManager, LinkService linkService) {
-        this.srManager = srManager;
-    }
-
-    /**
-     * Initialize LinkHandler.
-     */
-    void init() {
-        log.info("Loading stored links");
-        srManager.linkService.getActiveLinks().forEach(this::processLinkAdded);
-    }
-
-    /**
-     * Preprocessing of added link before being sent for route-path handling.
-     * Also performs post processing of link.
-     *
-     * @param link the link to be processed
-     */
-    void processLinkAdded(Link link) {
-        log.info("** LINK ADDED {}", link.toString());
-        if (!isLinkValid(link)) {
-            return;
-        }
-        // Irrespective of whether the local is a MASTER or not for this device,
-        // create group handler instance and push default TTP flow rules if needed,
-        // as in a multi-instance setup, instances can initiate groups for any
-        // device. Also update local groupHandler stores.
-        DefaultGroupHandler groupHandler = srManager.groupHandlerMap
-                                                .get(link.src().deviceId());
-        if (groupHandler == null) {
-            Device device = srManager.deviceService.getDevice(link.src().deviceId());
-            if (device != null) {
-                log.warn("processLinkAdded: Link Added notification without "
-                        + "Device Added event, still handling it");
-                srManager.processDeviceAdded(device);
-            }
-        }
-
-        if (isSeenLink(link)) {
-            // temp store retains previous state, just before the state is updated in
-            // seenLinks; previous state is necessary when processing the
-            // linkupdate in defaultRoutingHandler
-            seenBefore.add(link);
-        }
-        updateSeenLink(link, true);
-
-        if (srManager.deviceConfiguration == null ||
-                !srManager.deviceConfiguration.isConfigured(link.src().deviceId())) {
-            log.warn("Source device of this link is not configured.. "
-                    + "not processing further");
-            return;
-        }
-
-        // process link only if it is bidirectional
-        if (!isBidirectionalLinkUp(link)) {
-            log.debug("Link not bidirectional.. waiting for other direction " +
-                    "src {} --> dst {} ", link.dst(), link.src());
-            return;
-        }
-
-        log.info("processing bidi links {} <--> {} UP", link.src(), link.dst());
-        // update groupHandler internal port state for both directions
-        List<Link> ulinks = getBidiComponentLinks(link);
-        for (Link ulink : ulinks) {
-            DefaultGroupHandler gh = srManager.groupHandlerMap
-                                         .get(ulink.src().deviceId());
-            if (gh != null) {
-                gh.portUpForLink(ulink);
-            }
-        }
-
-        for (Link ulink : ulinks) {
-            log.info("-- Starting optimized route-path processing for component "
-                    + "unidirectional link {} --> {} UP", ulink.src(), ulink.dst());
-            srManager.defaultRoutingHandler
-                    .populateRoutingRulesForLinkStatusChange(null, ulink, null,
-                                                             seenBefore.contains(ulink));
-
-            if (srManager.mastershipService.isLocalMaster(ulink.src().deviceId())) {
-                // handle edge-ports for dual-homed hosts
-                updateHostPorts(ulink, true);
-
-                // It's possible that linkUp causes no route-path change as ECMP graph does
-                // not change if the link is a parallel link (same src-dst as
-                // another link). However we still need to update ECMP hash
-                // groups to include new buckets for the link that has come up.
-                DefaultGroupHandler gh = srManager.groupHandlerMap
-                                            .get(ulink.src().deviceId());
-                if (gh != null) {
-                    if (!seenBefore.contains(ulink) && isParallelLink(ulink)) {
-                        // if link seen first time, we need to ensure hash-groups have
-                        // all ports
-                        log.debug("Attempting retryHash for paralled first-time link {}",
-                                  ulink);
-                        gh.retryHash(ulink, false, true);
-                    } else {
-                        // seen before-link
-                        if (isParallelLink(ulink)) {
-                            log.debug("Attempting retryHash for paralled seen-before "
-                                    + "link {}", ulink);
-                            gh.retryHash(ulink, false, false);
-                        }
-                    }
-                }
-            }
-            //clean up temp state
-            seenBefore.remove(ulink);
-        }
-
-    }
-
-    /**
-     * Preprocessing of removed link before being sent for route-path handling.
-     * Also performs post processing of link.
-     *
-     * @param link the link to be processed
-     */
-    void processLinkRemoved(Link link) {
-        log.info("** LINK REMOVED {}", link.toString());
-        if (!isLinkValid(link)) {
-            return;
-        }
-        // when removing links, update seen links first, before doing route-path
-        // changes
-        updateSeenLink(link, false);
-        // handle edge-ports for dual-homed hosts
-        if (srManager.mastershipService.isLocalMaster(link.src().deviceId())) {
-            updateHostPorts(link, false);
-        }
-
-        // device availability check helps to ensure that multiple link-removed
-        // events are actually treated as a single switch removed event.
-        // purgeSeenLink is necessary so we do rerouting (instead of rehashing)
-        // when switch comes back.
-        if (link.src().elementId() instanceof DeviceId
-                && !srManager.deviceService.isAvailable(link.src().deviceId())) {
-            purgeSeenLink(link);
-            return;
-        }
-        if (link.dst().elementId() instanceof DeviceId
-                && !srManager.deviceService.isAvailable(link.dst().deviceId())) {
-            purgeSeenLink(link);
-            return;
-        }
-
-        // process link only if it is bidirectional
-        if (!isBidirectionalLinkDown(link)) {
-            log.debug("Link not bidirectional.. waiting for other direction " +
-                    "src {} --> dst {} ", link.dst(), link.src());
-            return;
-        }
-        log.info("processing bidi links {} <--> {} DOWN", link.src(), link.dst());
-
-        for (Link ulink : getBidiComponentLinks(link)) {
-            log.info("-- Starting optimized route-path processing for component "
-                    + "unidirectional link {} --> {} DOWN", ulink.src(), ulink.dst());
-            srManager.defaultRoutingHandler
-                .populateRoutingRulesForLinkStatusChange(ulink, null, null, true);
-
-            // attempt rehashing for parallel links
-            DefaultGroupHandler groupHandler = srManager.groupHandlerMap
-                    .get(ulink.src().deviceId());
-            if (groupHandler != null) {
-                if (srManager.mastershipService.isLocalMaster(ulink.src().deviceId())
-                        && isParallelLink(ulink)) {
-                    log.debug("* retrying hash for parallel link removed:{}", ulink);
-                    groupHandler.retryHash(ulink, true, false);
-                } else {
-                    log.debug("Not attempting retry-hash for link removed: {} .. {}",
-                              ulink,
-                              (srManager.mastershipService.isLocalMaster(ulink
-                                      .src().deviceId())) ? "not parallel"
-                                                          : "not master");
-                }
-                // ensure local stores are updated after all rerouting or rehashing
-                groupHandler.portDownForLink(ulink);
-            } else {
-                log.warn("group handler not found for dev:{} when removing link: {}",
-                         ulink.src().deviceId(), ulink);
-            }
-        }
-    }
-
-    /**
-     * Checks validity of link. Examples of invalid links include
-     * indirect-links, links between ports on the same switch, and more.
-     *
-     * @param link the link to be processed
-     * @return true if valid link
-     */
-     boolean isLinkValid(Link link) {
-        if (link.type() != Link.Type.DIRECT) {
-            // NOTE: A DIRECT link might be transiently marked as INDIRECT
-            // if BDDP is received before LLDP. We can safely ignore that
-            // until the LLDP is received and the link is marked as DIRECT.
-            log.info("Ignore link {}->{}. Link type is {} instead of DIRECT.",
-                     link.src(), link.dst(), link.type());
-            return false;
-        }
-        DeviceId srcId = link.src().deviceId();
-        DeviceId dstId = link.dst().deviceId();
-        if (srcId.equals(dstId)) {
-            log.warn("Links between ports on the same switch are not "
-                    + "allowed .. ignoring link {}", link);
-            return false;
-        }
-        DeviceConfiguration devConfig = srManager.deviceConfiguration;
-        if (devConfig == null) {
-            log.warn("Cannot check validity of link without device config");
-            return true;
-        }
-        try {
-            /*if (!devConfig.isEdgeDevice(srcId)
-                    && !devConfig.isEdgeDevice(dstId)) {
-                // ignore links between spines
-                // XXX revisit when handling multi-stage fabrics
-                log.warn("Links between spines not allowed...ignoring "
-                        + "link {}", link);
-                return false;
-            }*/
-            if (devConfig.isEdgeDevice(srcId)
-                    && devConfig.isEdgeDevice(dstId)) {
-                // ignore links between leaves if they are not pair-links
-                // XXX revisit if removing pair-link config or allowing more than
-                // one pair-link
-                if (devConfig.getPairDeviceId(srcId).equals(dstId)
-                        && devConfig.getPairLocalPort(srcId)
-                                .equals(link.src().port())
-                        && devConfig.getPairLocalPort(dstId)
-                                .equals(link.dst().port())) {
-                    // found pair link - allow it
-                    return true;
-                } else {
-                    log.warn("Links between leaves other than pair-links are "
-                            + "not allowed...ignoring link {}", link);
-                    return false;
-                }
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            // We still want to count the links in seenLinks even though there
-            // is no config. So we let it return true
-            log.warn("Could not check validity of link {} as subtending devices "
-                    + "are not yet configured", link);
-        }
-        return true;
-    }
-
-    /**
-     * Administratively enables or disables edge ports if the link that was
-     * added or removed was the only uplink port from an edge device. Edge ports
-     * that belong to dual-homed hosts are always processed. In addition,
-     * single-homed host ports are optionally processed depending on the
-     * singleHomedDown property.
-     *
-     * @param link the link to be processed
-     * @param added true if link was added, false if link was removed
-     */
-    private void updateHostPorts(Link link, boolean added) {
-        DeviceConfiguration devConfig = srManager.deviceConfiguration;
-        if (added) {
-            try {
-                if (!devConfig.isEdgeDevice(link.src().deviceId())
-                        || devConfig.isEdgeDevice(link.dst().deviceId())) {
-                    return;
-                }
-            } catch (DeviceConfigNotFoundException e) {
-                log.warn("Unable to determine if link is a valid uplink"
-                        + e.getMessage());
-            }
-            // re-enable previously disabled ports on this edge-device if any
-            Set<PortNumber> p = downedPortStore.remove(link.src().deviceId());
-            if (p != null) {
-                log.warn("Link src {} --> dst {} added is an edge-device uplink, "
-                        + "enabling dual homed ports if any: {}", link.src().deviceId(),
-                        link.dst().deviceId(), (p.isEmpty()) ? "no ports" : p);
-                p.forEach(pnum -> srManager.deviceAdminService
-                        .changePortState(link.src().deviceId(), pnum, true));
-            }
-        } else {
-            // If the device does not have a pair device - skip
-            DeviceId dev = link.src().deviceId();
-            if (getPairDeviceIdOrNull(dev) == null) {
-                log.info("Device {} does not have pair device " +
-                                 "not disabling access port", dev);
-                return;
-            }
-            // Verify if last uplink
-            if (!lastUplink(link)) {
-                return;
-            }
-            // find dual homed hosts on this dev to disable
-            Set<PortNumber> dp = srManager.hostHandler
-                    .getDualHomedHostPorts(dev);
-            log.warn("Link src {} --> dst {} removed was the last uplink, "
-                    + "disabling  dual homed ports:  {}", dev,
-                     link.dst().deviceId(), (dp.isEmpty()) ? "no ports" : dp);
-            dp.forEach(pnum -> srManager.deviceAdminService
-                        .changePortState(dev, pnum, false));
-            if (srManager.singleHomedDown) {
-                // get all configured ports and down them if they haven't already
-                // been downed
-                srManager.deviceService.getPorts(dev).stream()
-                    .filter(p -> p.isEnabled() && !dp.contains(p.number()))
-                    .filter(p -> srManager.interfaceService
-                            .isConfigured(new ConnectPoint(dev, p.number())))
-                    .filter(p -> !srManager.deviceConfiguration
-                            .isPairLocalPort(dev, p.number()))
-                    .forEach(p -> {
-                        log.warn("Last uplink gone src {} -> dst {} .. removing "
-                                + "configured port {}", p.number());
-                        srManager.deviceAdminService
-                            .changePortState(dev, p.number(), false);
-                        dp.add(p.number());
-                    });
-            }
-            if (!dp.isEmpty()) {
-                // update global store
-                Set<PortNumber> p = downedPortStore.get(dev);
-                if (p == null) {
-                    p = dp;
-                } else {
-                    p.addAll(dp);
-                }
-                downedPortStore.put(link.src().deviceId(), p);
-            }
-        }
-    }
-
-    /**
-     * Returns true if given link was the last active uplink from src-device of
-     * link. An uplink is defined as a unidirectional link with src as
-     * edgeRouter and dst as non-edgeRouter.
-     *
-     * @param link
-     * @return true if given link was the last uplink from the src device
-     */
-    private boolean lastUplink(Link link) {
-        DeviceConfiguration devConfig = srManager.deviceConfiguration;
-        try {
-            if (!devConfig.isEdgeDevice(link.src().deviceId())
-                    || devConfig.isEdgeDevice(link.dst().deviceId())) {
-                return false;
-            }
-            // note that using linkservice here would cause race conditions as
-            // more links can show up while the app is still processing the first one
-            Set<Link> devLinks = seenLinks.entrySet().stream()
-                    .filter(entry -> entry.getKey().src().deviceId()
-                            .equals(link.src().deviceId()))
-                    .filter(entry -> entry.getValue())
-                    .filter(entry -> !entry.getKey().equals(link))
-                    .map(entry -> entry.getKey())
-                    .collect(Collectors.toSet());
-
-            for (Link l : devLinks) {
-                if (devConfig.isEdgeDevice(l.dst().deviceId())) {
-                    continue;
-                }
-                log.debug("Found another active uplink {}", l);
-                return false;
-            }
-            log.debug("No active uplink found");
-            return true;
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn("Unable to determine if link was the last uplink"
-                    + e.getMessage());
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if this controller instance has seen this link before. The
-     * link may not be currently up, but as long as the link had been seen
-     * before this method will return true. The one exception is when the link
-     * was indeed seen before, but this controller instance was forced to forget
-     * it by a call to purgeSeenLink method.
-     *
-     * @param link the infrastructure link being queried
-     * @return true if this controller instance has seen this link before
-     */
-    boolean isSeenLink(Link link) {
-        return seenLinks.containsKey(link);
-    }
-
-    /**
-     * Updates the seen link store. Updates can be for links that are currently
-     * available or not.
-     *
-     * @param link the link to update in the seen-link local store
-     * @param up the status of the link, true if up, false if down
-     */
-    void updateSeenLink(Link link, boolean up) {
-        seenLinks.put(link, up);
-    }
-
-    /**
-     * Returns the status of a seen-link (up or down). If the link has not been
-     * seen-before, a null object is returned.
-     *
-     * @param link the infrastructure link being queried
-     * @return null if the link was not seen-before; true if the seen-link is
-     *         up; false if the seen-link is down
-     */
-    private Boolean isSeenLinkUp(Link link) {
-        return seenLinks.get(link);
-    }
-
-    /**
-     * Makes this controller instance forget a previously seen before link.
-     *
-     * @param link the infrastructure link to purge
-     */
-    private void purgeSeenLink(Link link) {
-        seenLinks.remove(link);
-        seenBefore.remove(link);
-    }
-
-    /**
-     * Returns the status of a link as parallel link. A parallel link is defined
-     * as a link which has common src and dst switches as another seen-link that
-     * is currently enabled. It is not necessary for the link being queried to
-     * be a seen-link.
-     *
-     * @param link the infrastructure link being queried
-     * @return true if a seen-link exists that is up, and shares the same src
-     *         and dst switches as the link being queried
-     */
-    private boolean isParallelLink(Link link) {
-        for (Entry<Link, Boolean> seen : seenLinks.entrySet()) {
-            Link seenLink = seen.getKey();
-            if (seenLink.equals(link)) {
-                continue;
-            }
-            if (seenLink.src().deviceId().equals(link.src().deviceId())
-                    && seenLink.dst().deviceId().equals(link.dst().deviceId())
-                    && seen.getValue()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if the link being queried is a bidirectional link that is
-     * up. A bidi-link is defined as a component unidirectional link, whose
-     * reverse link - ie. the component unidirectional link in the reverse
-     * direction - has been seen-before and is up. It is NOT necessary for the
-     * link being queried to be a previously seen-link.
-     *
-     * @param link the infrastructure (unidirectional) link being queried
-     * @return true if another unidirectional link exists in the reverse
-     *         direction, has been seen-before and is up
-     */
-    boolean isBidirectionalLinkUp(Link link) {
-        // cannot call linkService as link may be gone
-        Link reverseLink = getReverseLink(link);
-        if (reverseLink == null) {
-            return false;
-        }
-        Boolean result = isSeenLinkUp(reverseLink);
-        if (result == null) {
-            return false;
-        }
-        return result.booleanValue();
-    }
-
-    /**
-     * Returns true if the link being queried is a bidirectional link that is
-     * down. A bidi-link is defined as a component unidirectional link, whose
-     * reverse link - i.e the component unidirectional link in the reverse
-     * direction - has been seen before and is down. It is necessary for the
-     * reverse-link to have been previously seen.
-     *
-     * @param link the infrastructure (unidirectional) link being queried
-     * @return true if another unidirectional link exists in the reverse
-     *         direction, has been seen-before and is down
-     */
-    boolean isBidirectionalLinkDown(Link link) {
-        // cannot call linkService as link may be gone
-        Link reverseLink = getReverseLink(link);
-        if (reverseLink == null) {
-            log.warn("Query for bidi-link down but reverse-link not found "
-                    + "for link {}", link);
-            return false;
-        }
-        Boolean result = seenLinks.get(reverseLink);
-        if (result == null) {
-            return false;
-        }
-        // if reverse link is seen UP (true), then its not bidi yet
-        return !result.booleanValue();
-    }
-
-    /**
-     * Returns the link in the reverse direction from the given link, by
-     * consulting the seen-links store.
-     *
-     * @param link the given link
-     * @return the reverse link or null
-     */
-    Link getReverseLink(Link link) {
-        return seenLinks.keySet().stream()
-                .filter(l -> l.src().equals(link.dst()) && l.dst().equals(link.src()))
-                .findAny()
-                .orElse(null);
-    }
-
-    /**
-     * Returns the component unidirectional links of a declared bidirectional
-     * link, by consulting the seen-links store. Caller is responsible for
-     * previously verifying bidirectionality. Returned list may be empty if
-     * errors are encountered.
-     *
-     * @param link the declared bidirectional link
-     * @return list of component unidirectional links
-     */
-    List<Link> getBidiComponentLinks(Link link) {
-        Link reverseLink = getReverseLink(link);
-        List<Link> componentLinks;
-        if (reverseLink == null) { // really should not happen if link is bidi
-            log.error("cannot find reverse link for given link: {} ... is it "
-                    + "bi-directional?", link);
-            componentLinks = ImmutableList.of();
-        } else {
-            componentLinks = ImmutableList.of(reverseLink, link);
-        }
-        return componentLinks;
-    }
-
-    /**
-     * Determines if the given link should be avoided in routing calculations by
-     * policy or design.
-     *
-     * @param link the infrastructure link being queried
-     * @return true if link should be avoided
-     */
-    boolean avoidLink(Link link) {
-        // XXX currently only avoids all pair-links. In the future can be
-        // extended to avoid any generic link
-        DeviceId src = link.src().deviceId();
-        PortNumber srcPort = link.src().port();
-        DeviceConfiguration devConfig = srManager.deviceConfiguration;
-        if (devConfig == null || !devConfig.isConfigured(src)) {
-            log.warn("Device {} not configured..cannot avoid link {}", src,
-                     link);
-            return false;
-        }
-        DeviceId pairDev;
-        PortNumber pairLocalPort, pairRemotePort = null;
-        try {
-            pairDev = devConfig.getPairDeviceId(src);
-            pairLocalPort = devConfig.getPairLocalPort(src);
-            if (pairDev != null) {
-                pairRemotePort = devConfig
-                        .getPairLocalPort(pairDev);
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn("Pair dev for dev {} not configured..cannot avoid link {}",
-                     src, link);
-            return false;
-        }
-
-        return srcPort.equals(pairLocalPort)
-                && link.dst().deviceId().equals(pairDev)
-                && link.dst().port().equals(pairRemotePort);
-    }
-
-    /**
-     * Cleans up internal LinkHandler stores.
-     *
-     * @param device the device that has been removed
-     */
-    void processDeviceRemoved(Device device) {
-        seenLinks.keySet()
-                .removeIf(key -> key.src().deviceId().equals(device.id())
-                        || key.dst().deviceId().equals(device.id()));
-    }
-
-    /**
-     * Administratively disables the host location switchport if the edge device
-     * has no viable uplinks. The caller needs to determine if such behavior is
-     * desired for the single or dual-homed host.
-     *
-     * @param loc the host location
-     */
-    void checkUplinksForHost(HostLocation loc) {
-        // If the device does not have a pair device - return
-        if (getPairDeviceIdOrNull(loc.deviceId()) == null) {
-            log.info("Device {} does not have pair device " +
-                             "not disabling access port", loc.deviceId());
-            return;
-        }
-        // Verify link validity
-        try {
-            for (Link l : srManager.linkService.getDeviceLinks(loc.deviceId())) {
-                if (srManager.deviceConfiguration.isEdgeDevice(l.dst().deviceId())
-                        || l.state() == Link.State.INACTIVE) {
-                    continue;
-                }
-                // found valid uplink - so, nothing to do
-                return;
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn("Could not check for valid uplinks due to missing device"
-                    + "config " + e.getMessage());
-            return;
-        }
-        log.warn("Host location {} has no valid uplinks disabling port", loc);
-        srManager.deviceAdminService.changePortState(loc.deviceId(), loc.port(),
-                                                     false);
-        Set<PortNumber> p = downedPortStore.get(loc.deviceId());
-        if (p == null) {
-            p = Sets.newHashSet(loc.port());
-        } else {
-            p.add(loc.port());
-        }
-        downedPortStore.put(loc.deviceId(), p);
-    }
-
-    private DeviceId getPairDeviceIdOrNull(DeviceId deviceId) {
-        DeviceId pairDev;
-        try {
-            pairDev = srManager.deviceConfiguration.getPairDeviceId(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            pairDev = null;
-        }
-        return pairDev;
-    }
-
-    ImmutableMap<Link, Boolean> getSeenLinks() {
-        return ImmutableMap.copyOf(seenLinks);
-    }
-
-    ImmutableMap<DeviceId, Set<PortNumber>> getDownedPorts() {
-        return ImmutableMap.copyOf(downedPortStore.entrySet());
-    }
-
-    /**
-     * Returns all links that egress from given device that are UP in the
-     * seenLinks store. The returned links are also confirmed to be
-     * bidirectional.
-     *
-     * @param deviceId the device identifier
-     * @return set of egress links from the device
-     */
-    Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
-        return seenLinks.keySet().stream()
-                .filter(link -> link.src().deviceId().equals(deviceId))
-                .filter(link -> seenLinks.get(link))
-                .filter(link -> isBidirectionalLinkUp(link))
-                .collect(Collectors.toSet());
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java
deleted file mode 100644
index ac63f73..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2018-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;
-
-/**
- * Constants for default values of configurable properties.
- */
-public final class OsgiPropertyConstants {
-
-    private OsgiPropertyConstants() {}
-
-    public static final String PROP_ACTIVE_PROBING = "activeProbing";
-    public static final boolean ACTIVE_PROBING_DEFAULT = true;
-
-    public static final String PROP_SINGLE_HOMED_DOWN = "singleHomedDown";
-    public static final boolean SINGLE_HOMED_DOWN_DEFAULT = false;
-
-    public static final String PROP_RESPOND_TO_UNKNOWN_HOSTS = "respondToUnknownHosts";
-    public static final boolean RESPOND_TO_UNKNOWN_HOSTS_DEFAULT = true;
-
-    public static final String PROP_ROUTE_DOUBLE_TAGGED_HOSTS = "routeDoubleTaggedHosts";
-    public static final boolean ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT = false;
-
-    public static final String PROP_DEFAULT_INTERNAL_VLAN = "defaultInternalVlan";
-    public static final int DEFAULT_INTERNAL_VLAN_DEFAULT = 4094;
-
-    public static final String PROP_PW_TRANSPORT_VLAN = "pwTransportVlan";
-    public static final int PW_TRANSPORT_VLAN_DEFAULT = 4090;
-
-    static final String PROP_SYMMETRIC_PROBING = "symmetricProbing";
-    static final boolean SYMMETRIC_PROBING_DEFAULT = false;
-
-    public static final String PROP_ROUTE_SIMPLIFICATION = "routeSimplification";
-    public static final boolean ROUTE_SIMPLIFICATION_DEFAULT = false;
-
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Policy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Policy.java
deleted file mode 100644
index c9baf93..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Policy.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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;
-
-/**
- * Interface for Segment Routing Policy.
- */
-public interface Policy {
-    /**
-     * Enums for policy type.
-     */
-    enum Type {
-        /**
-         * Tunnel flow policy type.
-         */
-        TUNNEL_FLOW,
-
-        /**
-         * Load balancing policy type.
-         */
-        LOADBALANCE,
-
-        /**
-         * policy to avoid specific routers or links.
-         */
-        AVOID,
-
-        /**
-         * Access Control policy type.
-         */
-        DENY
-    }
-
-    /**
-     * Returns the policy ID.
-     *
-     * @return policy ID
-     */
-    String id();
-
-    /**
-     * Returns the priority of the policy.
-     *
-     * @return priority
-     */
-    int priority();
-
-    /**
-     * Returns the policy type.
-     *
-     * @return policy type
-     */
-    Type type();
-
-    /**
-     * Returns the source IP address of the policy.
-     *
-     * @return source IP address
-     */
-    String srcIp();
-
-    /**
-     * Returns the destination IP address of the policy.
-     *
-     * @return destination IP address
-     */
-    String dstIp();
-
-    /**
-     * Returns the IP protocol of the policy.
-     *
-     * @return IP protocol
-     */
-    String ipProto();
-
-    /**
-     * Returns the source port of the policy.
-     *
-     * @return source port
-     */
-    short srcPort();
-
-    /**
-     * Returns the destination of the policy.
-     *
-     * @return destination port
-     */
-    short dstPort();
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
deleted file mode 100644
index a341bb1..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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 org.onlab.packet.Ethernet;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.TpPort;
-import org.onosproject.cli.net.IpProtocol;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.slf4j.Logger;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Segment Routing Policy Handler.
- */
-public class PolicyHandler {
-
-    protected final Logger log = getLogger(getClass());
-
-    private ApplicationId appId;
-    private DeviceConfiguration deviceConfiguration;
-    private FlowObjectiveService flowObjectiveService;
-    private TunnelHandler tunnelHandler;
-    private final EventuallyConsistentMap<String, Policy> policyStore;
-    /**
-     * Result of policy creation.
-     */
-    public enum Result {
-        /**
-         * Success.
-         */
-        SUCCESS,
-
-        /**
-         * The same policy exists already.
-         */
-        POLICY_EXISTS,
-
-        /**
-         * The policy ID exists already.
-         */
-        ID_EXISTS,
-
-        /**
-         * Cannot find associated tunnel.
-         */
-        TUNNEL_NOT_FOUND,
-
-        /**
-         * Policy was not found.
-         */
-        POLICY_NOT_FOUND,
-
-        /**
-         * Policy type {} is not supported yet.
-         */
-        UNSUPPORTED_TYPE
-    }
-
-    /**
-     * Constructs policy handler.
-     *
-     * @param appId                segment routing application ID
-     * @param deviceConfiguration  DeviceConfiguration reference
-     * @param flowObjectiveService FlowObjectiveService reference
-     * @param tunnelHandler        tunnel handler reference
-     * @param policyStore          policy store
-     */
-    public PolicyHandler(ApplicationId appId,
-                         DeviceConfiguration deviceConfiguration,
-                         FlowObjectiveService flowObjectiveService,
-                         TunnelHandler tunnelHandler,
-                         EventuallyConsistentMap<String, Policy> policyStore) {
-        this.appId = appId;
-        this.deviceConfiguration = deviceConfiguration;
-        this.flowObjectiveService = flowObjectiveService;
-        this.tunnelHandler = tunnelHandler;
-        this.policyStore = policyStore;
-    }
-
-    /**
-     * Returns the policies.
-     *
-     * @return policy list
-     */
-    public List<Policy> getPolicies() {
-        return policyStore.values()
-                .stream()
-                .filter(policy -> policy instanceof TunnelPolicy)
-                .map(policy -> new TunnelPolicy((TunnelPolicy) policy))
-                .collect(Collectors.toList());
-    }
-
-    /**
-     * Creates a policy using the policy information given.
-     *  @param policy policy reference to create
-     *  @return ID_EXISTS if the same policy ID exists,
-     *  POLICY_EXISTS if the same policy exists, TUNNEL_NOT_FOUND if the tunnel
-     *  does not exists, UNSUPPORTED_TYPE if the policy type is not supported,
-     *  SUCCESS if the policy is created successfully
-     */
-    public Result createPolicy(Policy policy) {
-
-        if (policyStore.containsKey(policy.id())) {
-            log.warn("The policy id {} exists already", policy.id());
-            return Result.ID_EXISTS;
-        }
-
-        if (policyStore.containsValue(policy)) {
-            log.warn("The same policy exists already");
-            return Result.POLICY_EXISTS;
-        }
-
-        if (policy.type() == Policy.Type.TUNNEL_FLOW) {
-
-            TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
-            Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());
-            if (tunnel == null) {
-                return Result.TUNNEL_NOT_FOUND;
-            }
-
-            ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
-                    .builder()
-                    .fromApp(appId)
-                    .makePermanent()
-                    .nextStep(tunnel.groupId())
-                    .withPriority(tunnelPolicy.priority())
-                    .withSelector(buildSelector(policy))
-                    .withFlag(ForwardingObjective.Flag.VERSATILE);
-
-            DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
-            flowObjectiveService.forward(source, fwdBuilder.add());
-
-        } else {
-            log.warn("Policy type {} is not supported yet.", policy.type());
-            return Result.UNSUPPORTED_TYPE;
-        }
-
-        policyStore.put(policy.id(), policy);
-
-        return Result.SUCCESS;
-    }
-
-    /**
-     * Removes the policy given.
-     *
-     * @param policyInfo policy information to remove
-     * @return POLICY_NOT_FOUND if the policy to remove does not exists,
-     * SUCCESS if it is removed successfully
-     */
-    public Result removePolicy(Policy policyInfo) {
-
-        if (policyStore.get(policyInfo.id()) != null) {
-            Policy policy = policyStore.get(policyInfo.id());
-            if (policy.type() == Policy.Type.TUNNEL_FLOW) {
-                TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
-                Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());
-
-                ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
-                        .builder()
-                        .fromApp(appId)
-                        .makePermanent()
-                        .withSelector(buildSelector(policy))
-                        .withPriority(tunnelPolicy.priority())
-                        .nextStep(tunnel.groupId())
-                        .withFlag(ForwardingObjective.Flag.VERSATILE);
-
-                DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
-                flowObjectiveService.forward(source, fwdBuilder.remove());
-
-                policyStore.remove(policyInfo.id());
-            }
-        } else {
-            log.warn("Policy {} was not found", policyInfo.id());
-            return Result.POLICY_NOT_FOUND;
-        }
-
-        return Result.SUCCESS;
-    }
-
-
-    private TrafficSelector buildSelector(Policy policy) {
-
-        TrafficSelector.Builder tsb = DefaultTrafficSelector.builder();
-        tsb.matchEthType(Ethernet.TYPE_IPV4);
-        if (policy.dstIp() != null && !policy.dstIp().isEmpty()) {
-            tsb.matchIPDst(IpPrefix.valueOf(policy.dstIp()));
-        }
-        if (policy.srcIp() != null && !policy.srcIp().isEmpty()) {
-            tsb.matchIPSrc(IpPrefix.valueOf(policy.srcIp()));
-        }
-        if (policy.ipProto() != null && !policy.ipProto().isEmpty()) {
-            Short ipProto = IpProtocol.valueOf(policy.ipProto()).value();
-            tsb.matchIPProtocol(ipProto.byteValue());
-            if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.TCP)) {
-                if (policy.srcPort() != 0) {
-                    tsb.matchTcpSrc(TpPort.tpPort(policy.srcPort()));
-                }
-                if (policy.dstPort() != 0) {
-                    tsb.matchTcpDst(TpPort.tpPort(policy.dstPort()));
-                }
-            } else if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.UDP)) {
-                if (policy.srcPort() != 0) {
-                    tsb.matchUdpSrc(TpPort.tpPort(policy.srcPort()));
-                }
-                if (policy.dstPort() != 0) {
-                    tsb.matchUdpDst(TpPort.tpPort(policy.dstPort()));
-                }
-            }
-        }
-
-        return tsb.build();
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortAuthTracker.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortAuthTracker.java
deleted file mode 100644
index 2127019..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortAuthTracker.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright 2017-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.base.Objects;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.config.BlockedPortsConfig;
-import org.onosproject.utils.Comparators;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Keeps track of ports that have been configured for blocking,
- * and their current authentication state.
- */
-public class PortAuthTracker {
-
-    private static final Logger log = getLogger(PortAuthTracker.class);
-
-    private Map<DeviceId, Map<PortNumber, BlockState>> blockedPorts = new HashMap<>();
-    private Map<DeviceId, Map<PortNumber, BlockState>> oldMap;
-
-    @Override
-    public String toString() {
-        return "PortAuthTracker{entries = " + blockedPorts.size() + "}";
-    }
-
-    /**
-     * Changes the state of the given device id / port number pair to the
-     * specified state.
-     *
-     * @param d        device identifier
-     * @param p        port number
-     * @param newState the updated state
-     * @return true, if the state changed from what was previously mapped
-     */
-    private boolean changeStateTo(DeviceId d, PortNumber p, BlockState newState) {
-        Map<PortNumber, BlockState> portMap =
-                blockedPorts.computeIfAbsent(d, k -> new HashMap<>());
-        BlockState oldState =
-                portMap.computeIfAbsent(p, k -> BlockState.UNCHECKED);
-        portMap.put(p, newState);
-        return (oldState != newState);
-    }
-
-    /**
-     * Radius has authorized the supplicant at this connect point. If
-     * we are tracking this port, clear the blocking flow and mark the
-     * port as authorized.
-     *
-     * @param connectPoint supplicant connect point
-     */
-    void radiusAuthorize(ConnectPoint connectPoint) {
-        DeviceId d = connectPoint.deviceId();
-        PortNumber p = connectPoint.port();
-        if (configured(d, p)) {
-            clearBlockingFlow(d, p);
-            markAsAuthenticated(d, p);
-        }
-    }
-
-    /**
-     * Supplicant at specified connect point has logged off Radius. If
-     * we are tracking this port, install a blocking flow and mark the
-     * port as blocked.
-     *
-     * @param connectPoint supplicant connect point
-     */
-    void radiusLogoff(ConnectPoint connectPoint) {
-        DeviceId d = connectPoint.deviceId();
-        PortNumber p = connectPoint.port();
-        if (configured(d, p)) {
-            installBlockingFlow(d, p);
-            markAsBlocked(d, p);
-        }
-    }
-
-    /**
-     * Marks the specified device/port as blocked.
-     *
-     * @param d device id
-     * @param p port number
-     * @return true if the state changed (was not already blocked)
-     */
-    private boolean markAsBlocked(DeviceId d, PortNumber p) {
-        return changeStateTo(d, p, BlockState.BLOCKED);
-    }
-
-    /**
-     * Marks the specified device/port as authenticated.
-     *
-     * @param d device id
-     * @param p port number
-     * @return true if the state changed (was not already authenticated)
-     */
-    private boolean markAsAuthenticated(DeviceId d, PortNumber p) {
-        return changeStateTo(d, p, BlockState.AUTHENTICATED);
-    }
-
-    /**
-     * Returns true if the given device/port are configured for blocking.
-     *
-     * @param d device id
-     * @param p port number
-     * @return true if this device/port configured for blocking
-     */
-    private boolean configured(DeviceId d, PortNumber p) {
-        Map<PortNumber, BlockState> portMap = blockedPorts.get(d);
-        return portMap != null && portMap.get(p) != null;
-    }
-
-    private BlockState whatState(DeviceId d, PortNumber p,
-                                 Map<DeviceId, Map<PortNumber, BlockState>> m) {
-        Map<PortNumber, BlockState> portMap = m.get(d);
-        if (portMap == null) {
-            return BlockState.UNCHECKED;
-        }
-        BlockState state = portMap.get(p);
-        if (state == null) {
-            return BlockState.UNCHECKED;
-        }
-        return state;
-    }
-
-    /**
-     * Returns the current state of the given device/port.
-     *
-     * @param d device id
-     * @param p port number
-     * @return current block-state
-     */
-    BlockState currentState(DeviceId d, PortNumber p) {
-        return whatState(d, p, blockedPorts);
-    }
-
-    /**
-     * Returns the current state of the given connect point.
-     *
-     * @param cp connect point
-     * @return current block-state
-     */
-
-    BlockState currentState(ConnectPoint cp) {
-        return whatState(cp.deviceId(), cp.port(), blockedPorts);
-    }
-
-    /**
-     * Returns the number of entries being tracked.
-     *
-     * @return the number of tracked entries
-     */
-    int entryCount() {
-        int count = 0;
-        for (Map<PortNumber, BlockState> m : blockedPorts.values()) {
-            count += m.size();
-        }
-        return count;
-    }
-
-    /**
-     * Returns the previously recorded state of the given device/port.
-     *
-     * @param d device id
-     * @param p port number
-     * @return previous block-state
-     */
-    private BlockState oldState(DeviceId d, PortNumber p) {
-        return whatState(d, p, oldMap);
-    }
-
-    private void configurePort(DeviceId d, PortNumber p) {
-        boolean alreadyAuthenticated =
-                oldState(d, p) == BlockState.AUTHENTICATED;
-
-        if (alreadyAuthenticated) {
-            clearBlockingFlow(d, p);
-            markAsAuthenticated(d, p);
-        } else {
-            installBlockingFlow(d, p);
-            markAsBlocked(d, p);
-        }
-        log.info("Configuring port {}/{} as {}", d, p,
-                 alreadyAuthenticated ? "AUTHENTICATED" : "BLOCKED");
-    }
-
-    private boolean notInMap(DeviceId deviceId, PortNumber portNumber) {
-        Map<PortNumber, BlockState> m = blockedPorts.get(deviceId);
-        return m == null || m.get(portNumber) == null;
-    }
-
-    private void logPortsNoLongerBlocked() {
-        for (Map.Entry<DeviceId, Map<PortNumber, BlockState>> entry :
-                oldMap.entrySet()) {
-            DeviceId d = entry.getKey();
-            Map<PortNumber, BlockState> portMap = entry.getValue();
-
-            for (PortNumber p : portMap.keySet()) {
-                if (notInMap(d, p)) {
-                    clearBlockingFlow(d, p);
-                    log.info("De-configuring port {}/{} (UNCHECKED)", d, p);
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Reconfigures the port tracker using the supplied configuration.
-     *
-     * @param cfg the new configuration
-     */
-    void configurePortBlocking(BlockedPortsConfig cfg) {
-        // remember the old map; prepare a new map
-        oldMap = blockedPorts;
-        blockedPorts = new HashMap<>();
-
-        // for each configured device, add configured ports to map
-        for (String devId : cfg.deviceIds()) {
-            cfg.portIterator(devId)
-                    .forEachRemaining(p -> configurePort(deviceId(devId),
-                                                         portNumber(p)));
-        }
-
-        // have we de-configured any ports?
-        logPortsNoLongerBlocked();
-
-        // allow old map to be garbage collected
-        oldMap = null;
-    }
-
-    private List<PortAuthState> reportPortsAuthState() {
-        List<PortAuthState> result = new ArrayList<>();
-
-        for (Map.Entry<DeviceId, Map<PortNumber, BlockState>> entry :
-                blockedPorts.entrySet()) {
-            DeviceId d = entry.getKey();
-            Map<PortNumber, BlockState> portMap = entry.getValue();
-
-            for (PortNumber p : portMap.keySet()) {
-                result.add(new PortAuthState(d, p, portMap.get(p)));
-            }
-        }
-        Collections.sort(result);
-        return result;
-    }
-
-    /**
-     * Installs a "blocking" flow for device/port specified.
-     *
-     * @param d device id
-     * @param p port number
-     */
-    void installBlockingFlow(DeviceId d, PortNumber p) {
-        log.debug("Installing Blocking Flow at {}/{}", d, p);
-        // TODO: invoke SegmentRoutingService.block(...) appropriately
-        log.info("TODO >> Installing Blocking Flow at {}/{}", d, p);
-    }
-
-    /**
-     * Removes the "blocking" flow from device/port specified.
-     *
-     * @param d device id
-     * @param p port number
-     */
-    void clearBlockingFlow(DeviceId d, PortNumber p) {
-        log.debug("Clearing Blocking Flow from {}/{}", d, p);
-        // TODO: invoke SegmentRoutingService.block(...) appropriately
-        log.info("TODO >> Clearing Blocking Flow from {}/{}", d, p);
-    }
-
-
-    /**
-     * Designates the state of a given port. One of:
-     * <ul>
-     * <li> UNCHECKED: not configured for blocking </li>
-     * <li> BLOCKED: configured for blocking, and not yet authenticated </li>
-     * <li> AUTHENTICATED: configured for blocking, but authenticated </li>
-     * </ul>
-     */
-    public enum BlockState {
-        UNCHECKED,
-        BLOCKED,
-        AUTHENTICATED
-    }
-
-    /**
-     * A simple DTO binding of device identifier, port number, and block state.
-     */
-    public static final class PortAuthState implements Comparable<PortAuthState> {
-        private final DeviceId d;
-        private final PortNumber p;
-        private final BlockState s;
-
-        private PortAuthState(DeviceId d, PortNumber p, BlockState s) {
-            this.d = d;
-            this.p = p;
-            this.s = s;
-        }
-
-        @Override
-        public String toString() {
-            return String.valueOf(d) + "/" + p + " -- " + s;
-        }
-
-        @Override
-        public int compareTo(PortAuthState o) {
-            // NOTE: only compare against "deviceid/port"
-            int result = Comparators.ELEMENT_ID_COMPARATOR.compare(d, o.d);
-            return (result != 0) ? result : Long.signum(p.toLong() - o.p.toLong());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final PortAuthTracker.PortAuthState that = (PortAuthTracker.PortAuthState) obj;
-
-            return Comparators.ELEMENT_ID_COMPARATOR.compare(this.d, that.d) == 0 &&
-                    p.toLong() == that.p.toLong();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(this.d, this.p);
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortFilterInfo.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortFilterInfo.java
deleted file mode 100644
index 75c12d6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortFilterInfo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2018-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.base.MoreObjects;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Utility class used to temporarily store information about the ports on a
- * device processed for filtering objectives.
- */
-public final class PortFilterInfo {
-    int disabledPorts = 0, errorPorts = 0, filteredPorts = 0;
-
-    public PortFilterInfo(int disabledPorts, int errorPorts,
-                          int filteredPorts) {
-        this.disabledPorts = disabledPorts;
-        this.filteredPorts = filteredPorts;
-        this.errorPorts = errorPorts;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(disabledPorts, filteredPorts, errorPorts);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if ((obj == null) || (!(obj instanceof PortFilterInfo))) {
-            return false;
-        }
-        PortFilterInfo other = (PortFilterInfo) obj;
-        return ((disabledPorts == other.disabledPorts) &&
-                (filteredPorts == other.filteredPorts) &&
-                (errorPorts == other.errorPorts));
-    }
-
-    @Override
-    public String toString() {
-        MoreObjects.ToStringHelper helper = toStringHelper(this)
-                .add("disabledPorts", disabledPorts)
-                .add("errorPorts", errorPorts)
-                .add("filteredPorts", filteredPorts);
-        return helper.toString();
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
deleted file mode 100644
index d9372fe..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright 2016-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.Sets;
-
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteEvent;
-import org.onosproject.net.DeviceId;
-import org.onosproject.routeservice.RouteInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Handles RouteEvent and manages routing entries.
- */
-public class RouteHandler {
-    private static final Logger log = LoggerFactory.getLogger(RouteHandler.class);
-    private final SegmentRoutingManager srManager;
-
-    RouteHandler(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-    }
-
-    protected void init(DeviceId deviceId) {
-        srManager.routeService.getRouteTables().stream()
-                .map(srManager.routeService::getRoutes)
-                .flatMap(Collection::stream)
-                .map(RouteInfo::allRoutes)
-                .filter(allRoutes -> allRoutes.stream().anyMatch(resolvedRoute ->
-                        srManager.nextHopLocations(resolvedRoute).stream()
-                                .anyMatch(cp -> deviceId.equals(cp.deviceId()))))
-                .forEach(rr -> processRouteAddedInternal(rr, true));
-    }
-
-    void processRouteAdded(RouteEvent event) {
-        processRouteAddedInternal(event.alternatives(), false);
-    }
-
-    /**
-     * Internal logic that handles route addition.
-     *
-     * @param routes collection of routes to be processed
-     * @param populateRouteOnly true if we only want to populateRoute but not populateSubnet.
-     *                          Set it to true when initializing a device coming up.
-     *                          populateSubnet will be done when link comes up later so it is redundant.
-     *                          populateRoute still needs to be done for statically configured next hop hosts.
-     */
-    private void processRouteAddedInternal(Collection<ResolvedRoute> routes, boolean populateRouteOnly) {
-        if (!isReady()) {
-            log.info("System is not ready. Skip adding route for {}", routes);
-            return;
-        }
-
-        log.info("processRouteAddedInternal. routes={}", routes);
-
-        if (routes.size() > 2) {
-            log.info("Route {} has more than two next hops. Do not process route change", routes);
-            return;
-        }
-
-        ResolvedRoute rr = routes.stream().findFirst().orElse(null);
-        if (rr == null) {
-            log.warn("No resolved route found. Abort processRouteAddedInternal");
-        }
-
-        Set<ConnectPoint> allLocations = Sets.newHashSet();
-        Set<IpPrefix> allPrefixes = Sets.newHashSet();
-        routes.forEach(route -> {
-            allLocations.addAll(srManager.nextHopLocations(route));
-            allPrefixes.add(route.prefix());
-        });
-        log.debug("RouteAdded. populateSubnet {}, {}", allLocations, allPrefixes);
-        srManager.defaultRoutingHandler.populateSubnet(allLocations, allPrefixes);
-
-
-        routes.forEach(route -> {
-            IpPrefix prefix = route.prefix();
-            MacAddress nextHopMac = route.nextHopMac();
-            VlanId nextHopVlan = route.nextHopVlan();
-            Set<ConnectPoint> locations = srManager.nextHopLocations(route);
-
-            locations.forEach(location -> {
-                log.debug("RouteAdded. addSubnet {}, {}", location, prefix);
-                srManager.deviceConfiguration.addSubnet(location, prefix);
-                log.debug("RouteAdded populateRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
-                srManager.defaultRoutingHandler.populateRoute(location.deviceId(), prefix,
-                        nextHopMac, nextHopVlan, location.port(), false);
-            });
-        });
-    }
-
-    void processRouteUpdated(RouteEvent event) {
-        processRouteUpdatedInternal(Sets.newHashSet(event.alternatives()),
-                Sets.newHashSet(event.prevAlternatives()));
-    }
-
-    void processAlternativeRoutesChanged(RouteEvent event) {
-        processRouteUpdatedInternal(Sets.newHashSet(event.alternatives()),
-                Sets.newHashSet(event.prevAlternatives()));
-    }
-
-    private void processRouteUpdatedInternal(Set<ResolvedRoute> routes, Set<ResolvedRoute> oldRoutes) {
-        if (!isReady()) {
-            log.info("System is not ready. Skip updating route for {} -> {}", oldRoutes, routes);
-            return;
-        }
-
-        log.info("processRouteUpdatedInternal. routes={}, oldRoutes={}", routes, oldRoutes);
-
-        if (routes.size() > 2) {
-            log.info("Route {} has more than two next hops. Do not process route change", routes);
-            return;
-        }
-
-        Set<ConnectPoint> allLocations = Sets.newHashSet();
-        Set<IpPrefix> allPrefixes = Sets.newHashSet();
-        routes.forEach(route -> {
-            allLocations.addAll(srManager.nextHopLocations(route));
-            allPrefixes.add(route.prefix());
-        });
-
-        // Just come back from an invalid next hop count
-        // Revoke subnet from all locations and reset oldRoutes such that system will be reprogrammed from scratch
-        if (oldRoutes.size() > 2) {
-            log.info("Revoke subnet {} and reset oldRoutes");
-            srManager.defaultRoutingHandler.revokeSubnet(allPrefixes);
-            oldRoutes = Sets.newHashSet();
-        }
-
-        log.debug("RouteUpdated. populateSubnet {}, {}", allLocations, allPrefixes);
-        srManager.defaultRoutingHandler.populateSubnet(allLocations, allPrefixes);
-
-        Set<ResolvedRoute> toBeRemoved = Sets.difference(oldRoutes, routes).immutableCopy();
-        Set<ResolvedRoute> toBeAdded = Sets.difference(routes, oldRoutes).immutableCopy();
-
-        toBeRemoved.forEach(route -> {
-            srManager.nextHopLocations(route).forEach(oldLocation -> {
-                if (toBeAdded.stream().map(srManager::nextHopLocations)
-                        .flatMap(Set::stream).map(ConnectPoint::deviceId)
-                        .noneMatch(deviceId -> deviceId.equals(oldLocation.deviceId()))) {
-                    IpPrefix prefix = route.prefix();
-                    log.debug("RouteUpdated. removeSubnet {}, {}", oldLocation, prefix);
-                    srManager.deviceConfiguration.removeSubnet(oldLocation, prefix);
-                    // We don't remove the flow on the old location in occasion of two next hops becoming one
-                    // since the populateSubnet will point the old location to the new location via spine.
-                }
-            });
-        });
-
-        toBeAdded.forEach(route -> {
-            IpPrefix prefix = route.prefix();
-            MacAddress nextHopMac = route.nextHopMac();
-            VlanId nextHopVlan = route.nextHopVlan();
-            Set<ConnectPoint> locations = srManager.nextHopLocations(route);
-
-            locations.forEach(location -> {
-                log.debug("RouteUpdated. addSubnet {}, {}", location, prefix);
-                srManager.deviceConfiguration.addSubnet(location, prefix);
-                log.debug("RouteUpdated. populateRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
-                srManager.defaultRoutingHandler.populateRoute(location.deviceId(), prefix,
-                        nextHopMac, nextHopVlan, location.port(), false);
-            });
-        });
-    }
-
-    void processRouteRemoved(RouteEvent event) {
-        processRouteRemovedInternal(event.alternatives());
-    }
-
-    private void processRouteRemovedInternal(Collection<ResolvedRoute> routes) {
-        if (!isReady()) {
-            log.info("System is not ready. Skip removing route for {}", routes);
-            return;
-        }
-
-        log.info("processRouteRemovedInternal. routes={}", routes);
-
-        Set<IpPrefix> allPrefixes = Sets.newHashSet();
-        routes.forEach(route -> {
-            allPrefixes.add(route.prefix());
-        });
-        log.debug("RouteRemoved. revokeSubnet {}", allPrefixes);
-        srManager.defaultRoutingHandler.revokeSubnet(allPrefixes);
-
-        routes.forEach(route -> {
-            IpPrefix prefix = route.prefix();
-            MacAddress nextHopMac = route.nextHopMac();
-            VlanId nextHopVlan = route.nextHopVlan();
-            Set<ConnectPoint> locations = srManager.nextHopLocations(route);
-
-            locations.forEach(location -> {
-                log.debug("RouteRemoved. removeSubnet {}, {}", location, prefix);
-                srManager.deviceConfiguration.removeSubnet(location, prefix);
-                // We don't need to call revokeRoute again since revokeSubnet will remove the prefix
-                // from all devices, including the ones that next hop attaches to.
-
-                // Also remove redirection flows on the pair device if exists.
-                Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
-                Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(location.deviceId());
-                if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
-                    // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
-                    //       when the host is untagged
-                    VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(nextHopVlan);
-
-                    log.debug("RouteRemoved. revokeRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
-                    srManager.defaultRoutingHandler.revokeRoute(pairDeviceId.get(), prefix,
-                            nextHopMac, vlanId, pairLocalPort.get(), false);
-                }
-            });
-        });
-    }
-
-    void processHostMovedEvent(HostEvent event) {
-        log.info("processHostMovedEvent {}", event);
-        MacAddress hostMac = event.subject().mac();
-        VlanId hostVlanId = event.subject().vlan();
-
-        Set<HostLocation> prevLocations = event.prevSubject().locations();
-        Set<HostLocation> newLocations = event.subject().locations();
-        Set<ConnectPoint> connectPoints = newLocations.stream()
-                .map(l -> (ConnectPoint) l).collect(Collectors.toSet());
-        List<Set<IpPrefix>> batchedSubnets =
-                srManager.deviceConfiguration.getBatchedSubnets(event.subject().id());
-        Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId)
-                .collect(Collectors.toSet());
-
-        // Set of deviceIDs of the previous locations where the host was connected
-        // Used to determine if host moved to different connect points
-        // on same device or moved to a different device altogether
-        Set<DeviceId> oldDeviceIds = prevLocations.stream().map(HostLocation::deviceId)
-                .collect(Collectors.toSet());
-
-        // L3 Ucast bucket needs to be updated only once per host
-        // and only when the no. of routes with the host as next-hop is not zero
-        if (!batchedSubnets.isEmpty()) {
-           // For each new location, if NextObj exists for the host, update with new location ..
-           Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
-                  int nextId = srManager.getMacVlanNextObjectiveId(newLocation.deviceId(),
-                                                                   hostMac, hostVlanId, null, false);
-                  VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(newLocation)).orElse(hostVlanId);
-
-                  if (nextId != -1) {
-                      //Update the nextId group bucket
-                      log.debug("HostMoved. NextId exists, update L3 Ucast Group Bucket {}, {}, {} --> {}",
-                                             newLocation, hostMac, vlanId, nextId);
-                      srManager.updateMacVlanTreatment(newLocation.deviceId(), hostMac, vlanId,
-                                                       newLocation.port(), nextId);
-                  } else {
-                      log.debug("HostMoved. NextId does not exist for this location {}, host {}/{}",
-                                              newLocation, hostMac, vlanId);
-                  }
-           });
-        }
-
-        batchedSubnets.forEach(subnets -> {
-            log.debug("HostMoved. populateSubnet {}, {}", newLocations, subnets);
-            srManager.defaultRoutingHandler.populateSubnet(connectPoints, subnets);
-
-            subnets.forEach(prefix -> {
-                // For each old location
-                Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
-
-                    // Remove flows for unchanged IPs only when the host moves from a switch to another.
-                    // Otherwise, do not remove and let the adding part update the old flow
-                    if (newDeviceIds.contains(prevLocation.deviceId())) {
-                        return;
-                    }
-
-                    log.debug("HostMoved. removeSubnet {}, {}", prevLocation, prefix);
-                    srManager.deviceConfiguration.removeSubnet(prevLocation, prefix);
-
-                    // Do not remove flow from a device if the route is still reachable via its pair device.
-                    // populateSubnet will update the flow to point to its pair device via spine.
-                    DeviceId pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId()).orElse(null);
-                    if (newLocations.stream().anyMatch(n -> n.deviceId().equals(pairDeviceId))) {
-                        return;
-                    }
-
-                    log.debug("HostMoved. revokeRoute {}, {}, {}, {}", prevLocation, prefix, hostMac, hostVlanId);
-                    srManager.defaultRoutingHandler.revokeRoute(prevLocation.deviceId(), prefix,
-                            hostMac, hostVlanId, prevLocation.port(), false);
-                });
-
-                // For each new location, add all new IPs.
-                Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
-                    log.debug("HostMoved. addSubnet {}, {}", newLocation, prefix);
-                    srManager.deviceConfiguration.addSubnet(newLocation, prefix);
-
-                    //its a new connect point, not a move from an existing device, populateRoute
-                    if (!oldDeviceIds.contains(newLocation.deviceId())) {
-                       log.debug("HostMoved. populateRoute {}, {}, {}, {}", newLocation, prefix, hostMac, hostVlanId);
-                       srManager.defaultRoutingHandler.populateRoute(newLocation.deviceId(), prefix,
-                              hostMac, hostVlanId, newLocation.port(), false);
-                    }
-                });
-            });
-        });
-
-    }
-
-    private boolean isReady() {
-        return Objects.nonNull(srManager.deviceConfiguration) &&
-                Objects.nonNull(srManager.defaultRoutingHandler);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteSimplifierUtils.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteSimplifierUtils.java
deleted file mode 100644
index 401007c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteSimplifierUtils.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2019-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.ImmutableList;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-
-/**
- * Utility class for route simplification.
- */
-final class RouteSimplifierUtils {
-
-    /*
-     * When route with source type listed in leafExclusionRouteTypes,
-     * it will programme only on the leaf pair the nexthop attaches to. Other leaves will be ignored.
-     */
-    private static final ImmutableList<Route.Source> LEAF_EXCLUSION_ROUTE_TYPES =
-            ImmutableList.of(Route.Source.DHCP, Route.Source.RIP, Route.Source.DHCPLQ);
-
-    private SegmentRoutingManager srManager;
-
-    RouteSimplifierUtils(SegmentRoutingManager srManager) {
-
-        this.srManager = srManager;
-    }
-
-    /**
-     * Checking whether the leafExclusionRouteTypes contains the given source type.
-     *
-     * @param s source type
-     * @return boolean if it containsd the source type.
-     *
-     */
-    public boolean hasLeafExclusionEnabledForType(Route.Source s) {
-        return LEAF_EXCLUSION_ROUTE_TYPES.contains(s);
-    }
-
-    /**
-     * When route with any source of given prefix is  listed in leafExclusionRouteTypes,
-     * it will programme only on the leaf pair the nexthop attaches to. Other leaves will be ignored.
-     *
-     * @param ipPrefix  ip prefix of the route.
-     * @return boolean if contains the prefix of the mentioned source type.
-     */
-    public boolean hasLeafExclusionEnabledForPrefix(IpPrefix ipPrefix) {
-        for (ResolvedRoute route : srManager.routeService.getAllResolvedRoutes(ipPrefix)) {
-            if (hasLeafExclusionEnabledForType(route.route().source())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
deleted file mode 100644
index a6f6e32..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ /dev/null
@@ -1,1942 +0,0 @@
-/*
- * 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.Lists;
-import com.google.common.collect.Sets;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.onlab.packet.EthType;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.Host;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.packet.PacketPriority;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective.Builder;
-import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onlab.packet.Ethernet.TYPE_ARP;
-import static org.onlab.packet.Ethernet.TYPE_IPV6;
-import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
-import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
-import static org.onlab.packet.ICMP6.ROUTER_ADVERTISEMENT;
-import static org.onlab.packet.ICMP6.ROUTER_SOLICITATION;
-import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
-import static org.onosproject.segmentrouting.SegmentRoutingService.DEFAULT_PRIORITY;
-
-/**
- * Populator of segment routing flow rules.
- */
-public class RoutingRulePopulator {
-    private static final Logger log = LoggerFactory.getLogger(RoutingRulePopulator.class);
-
-    private static final int ARP_NDP_PRIORITY = 30000;
-
-    private AtomicLong rulePopulationCounter;
-    private SegmentRoutingManager srManager;
-    private DeviceConfiguration config;
-    private RouteSimplifierUtils routeSimplifierUtils;
-
-    // used for signalling the driver to remove vlan table and tmac entry also
-    private static final long CLEANUP_DOUBLE_TAGGED_HOST_ENTRIES = 1;
-    private static final long DOUBLE_TAGGED_METADATA_MASK = 0xffffffffffffffffL;
-
-    /**
-     * Creates a RoutingRulePopulator object.
-     *
-     * @param srManager segment routing manager reference
-     */
-    RoutingRulePopulator(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-        this.config = checkNotNull(srManager.deviceConfiguration);
-        this.rulePopulationCounter = new AtomicLong(0);
-        this.routeSimplifierUtils = new RouteSimplifierUtils(srManager);
-    }
-
-    /**
-     * Resets the population counter.
-     */
-    void resetCounter() {
-        rulePopulationCounter.set(0);
-    }
-
-    /**
-     * Returns the number of rules populated.
-     *
-     * @return number of rules
-     */
-    long getCounter() {
-        return rulePopulationCounter.get();
-    }
-
-    /**
-     * Populate a bridging rule on given deviceId that matches given mac, given vlan and
-     * output to given port.
-     *
-     * @param deviceId device ID
-     * @param port port
-     * @param mac mac address
-     * @param vlanId VLAN ID
-     * @return future that carries the flow objective if succeeded, null if otherwise
-     */
-    CompletableFuture<Objective> populateBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
-        ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, false);
-        if (fob == null) {
-            log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
-            return CompletableFuture.completedFuture(null);
-        }
-
-        CompletableFuture<Objective> future = new CompletableFuture<>();
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> {
-                    log.debug("Brigding rule for {}/{} populated", mac, vlanId);
-                    future.complete(objective);
-                },
-                (objective, error) -> {
-                    log.warn("Failed to populate bridging rule for {}/{}: {}", mac, vlanId, error);
-                    future.complete(null);
-                });
-        srManager.flowObjectiveService.forward(deviceId, fob.add(context));
-        return future;
-    }
-
-    /**
-     * Revoke a bridging rule on given deviceId that matches given mac, given vlan and
-     * output to given port.
-     *
-     * @param deviceId device ID
-     * @param port port
-     * @param mac mac address
-     * @param vlanId VLAN ID
-     * @return future that carries the flow objective if succeeded, null if otherwise
-     */
-    CompletableFuture<Objective> revokeBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
-        ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, true);
-        if (fob == null) {
-            log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
-            return CompletableFuture.completedFuture(null);
-        }
-
-        CompletableFuture<Objective> future = new CompletableFuture<>();
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> {
-                    log.debug("Brigding rule for {}/{} revoked", mac, vlanId);
-                    future.complete(objective);
-                },
-                (objective, error) -> {
-                    log.warn("Failed to revoke bridging rule for {}/{}: {}", mac, vlanId, error);
-                    future.complete(null);
-                });
-        srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
-        return future;
-    }
-
-    /**
-     * Generates a forwarding objective builder for bridging rules.
-     * <p>
-     * The forwarding objective bridges packets destined to a given MAC to
-     * given port on given device.
-     *
-     * @param deviceId Device that host attaches to
-     * @param mac MAC address of the host
-     * @param hostVlanId VLAN ID of the host
-     * @param outport Port that host attaches to
-     * @param revoke true if forwarding objective is meant to revoke forwarding rule
-     * @return Forwarding objective builder
-     */
-    private ForwardingObjective.Builder bridgingFwdObjBuilder(
-            DeviceId deviceId, MacAddress mac, VlanId hostVlanId, PortNumber outport, boolean revoke) {
-        ConnectPoint connectPoint = new ConnectPoint(deviceId, outport);
-        VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
-        Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
-        VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
-        // Create host selector
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        sbuilder.matchEthDst(mac);
-
-        // Create host treatment
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.immediate().setOutput(outport);
-
-        // Create host meta
-        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-
-        // Adjust the selector, treatment and meta according to VLAN configuration
-        if (taggedVlans.contains(hostVlanId)) {
-            sbuilder.matchVlanId(hostVlanId);
-            mbuilder.matchVlanId(hostVlanId);
-        } else if (hostVlanId.equals(VlanId.NONE)) {
-            if (untaggedVlan != null) {
-                sbuilder.matchVlanId(untaggedVlan);
-                mbuilder.matchVlanId(untaggedVlan);
-                tbuilder.immediate().popVlan();
-            } else if (nativeVlan != null) {
-                sbuilder.matchVlanId(nativeVlan);
-                mbuilder.matchVlanId(nativeVlan);
-                tbuilder.immediate().popVlan();
-            } else {
-                log.warn("Untagged host {}/{} is not allowed on {} without untagged or native" +
-                        "vlan config", mac, hostVlanId, connectPoint);
-                return null;
-            }
-        } else {
-            log.warn("Tagged host {}/{} is not allowed on {} without VLAN listed in tagged vlan",
-                    mac, hostVlanId, connectPoint);
-            return null;
-        }
-
-        // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
-        // If the objective is to revoke an existing rule, and for some reason
-        // the next-objective does not exist, then a new one should not be created
-        int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport,
-                tbuilder.build(), mbuilder.build(), !revoke);
-        if (portNextObjId == -1) {
-            // Warning log will come from getPortNextObjective method
-            return null;
-        }
-
-        return DefaultForwardingObjective.builder()
-                .withFlag(ForwardingObjective.Flag.SPECIFIC)
-                .withSelector(sbuilder.build())
-                .nextStep(portNextObjId)
-                .withPriority(100)
-                .fromApp(srManager.appId)
-                .makePermanent();
-    }
-
-    /**
-     * Populate or revoke a bridging rule on given deviceId that matches given vlanId,
-     * and hostMAC connected to given port, and output to given port only when
-     * vlan information is valid.
-     *
-     * @param deviceId device ID that host attaches to
-     * @param portNum port number that host attaches to
-     * @param hostMac mac address of the host connected to the switch port
-     * @param vlanId Vlan ID configured on the switch port
-     * @param popVlan true to pop Vlan tag at TrafficTreatment, false otherwise
-     * @param install true to populate the objective, false to revoke
-     */
-    // TODO Refactor. There are a lot of duplications between this method, populateBridging,
-    //      revokeBridging and bridgingFwdObjBuilder.
-    void updateBridging(DeviceId deviceId, PortNumber portNum, MacAddress hostMac,
-                        VlanId vlanId, boolean popVlan, boolean install) {
-        // Create host selector
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        sbuilder.matchEthDst(hostMac);
-
-        // Create host meta
-        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-
-        sbuilder.matchVlanId(vlanId);
-        mbuilder.matchVlanId(vlanId);
-
-        // Create host treatment
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.immediate().setOutput(portNum);
-
-        if (popVlan) {
-            tbuilder.immediate().popVlan();
-        }
-
-        int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNum,
-                tbuilder.build(), mbuilder.build(), install);
-        if (portNextObjId != -1) {
-            ForwardingObjective.Builder fob = DefaultForwardingObjective.builder()
-                    .withFlag(ForwardingObjective.Flag.SPECIFIC)
-                    .withSelector(sbuilder.build())
-                    .nextStep(portNextObjId)
-                    .withPriority(100)
-                    .fromApp(srManager.appId)
-                    .makePermanent();
-
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("Brigding rule for {}/{} {}", hostMac, vlanId,
-                            install ? "populated" : "revoked"),
-                    (objective, error) -> log.warn("Failed to {} bridging rule for {}/{}: {}",
-                            install ? "populate" : "revoke", hostMac, vlanId, error));
-            srManager.flowObjectiveService.forward(deviceId, install ? fob.add(context) : fob.remove(context));
-        } else {
-            log.warn("Failed to retrieve next objective for {}/{}", hostMac, vlanId);
-        }
-    }
-
-    /**
-     * Populates IP rules for a route that has direct connection to the switch.
-     * This method should not be invoked directly without going through DefaultRoutingHandler.
-     *
-     * @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
-     * @return future that carries the flow objective if succeeded, null if otherwise
-     */
-    CompletableFuture<Objective> populateRoute(DeviceId deviceId, IpPrefix prefix,
-                              MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
-        log.debug("Populate direct routing entry for route {} at {}:{}",
-                prefix, deviceId, outPort);
-        ForwardingObjective.Builder fwdBuilder;
-        try {
-            fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac,
-                                              hostVlanId, outPort, null, null, directHost, false);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting direct populateRoute");
-            return CompletableFuture.completedFuture(null);
-        }
-        if (fwdBuilder == null) {
-            log.warn("Aborting host routing table entry due "
-                    + "to error for dev:{} route:{}", deviceId, prefix);
-            return CompletableFuture.completedFuture(null);
-        }
-
-        int nextId = fwdBuilder.add().nextId();
-        CompletableFuture<Objective> future = new CompletableFuture<>();
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> {
-                    log.debug("Direct routing rule for route {} populated. nextId={}", prefix, nextId);
-                    future.complete(objective);
-                },
-                (objective, error) -> {
-                    log.warn("Failed to populate direct routing rule for route {}: {}", prefix, error);
-                    future.complete(null);
-                });
-        srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
-        rulePopulationCounter.incrementAndGet();
-        return future;
-    }
-
-    /**
-     * Removes IP rules for a route when the next hop is gone.
-     * This method should not be invoked directly without going through DefaultRoutingHandler.
-     *
-     * @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
-     * @return future that carries the flow objective if succeeded, null if otherwise
-     */
-    CompletableFuture<Objective> revokeRoute(DeviceId deviceId, IpPrefix prefix,
-            MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
-        log.debug("Revoke IP table entry for route {} at {}:{}",
-                prefix, deviceId, outPort);
-        ForwardingObjective.Builder fwdBuilder;
-        try {
-            fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac,
-                                              hostVlanId, outPort, null, null, directHost, true);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting revokeIpRuleForHost.");
-            return CompletableFuture.completedFuture(null);
-        }
-        if (fwdBuilder == null) {
-            log.warn("Aborting host routing table entries due "
-                    + "to error for dev:{} route:{}", deviceId, prefix);
-            return CompletableFuture.completedFuture(null);
-        }
-
-        CompletableFuture<Objective> future = new CompletableFuture<>();
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> {
-                    log.debug("IP rule for route {} revoked", prefix);
-                    future.complete(objective);
-                },
-                (objective, error) -> {
-                    log.warn("Failed to revoke IP rule for route {}: {}", prefix, error);
-                    future.complete(null);
-                });
-        srManager.flowObjectiveService.forward(deviceId, fwdBuilder.remove(context));
-        return future;
-    }
-
-    /**
-     * Returns a forwarding objective builder for routing rules.
-     * <p>
-     * The forwarding objective routes packets destined to a given prefix to
-     * given port on given device with given destination MAC.
-     *
-     * @param deviceId device ID
-     * @param prefix prefix that need to be routed
-     * @param hostMac MAC address of the nexthop
-     * @param hostVlanId Vlan ID of the nexthop
-     * @param outPort port where the nexthop attaches to
-     * @param revoke true if forwarding objective is meant to revoke forwarding rule
-     * @param directHost host is direct or indirect
-     * @return forwarding objective builder
-     * @throws DeviceConfigNotFoundException if given device is not configured
-     */
-
-    private ForwardingObjective.Builder routingFwdObjBuilder(
-            DeviceId deviceId, IpPrefix prefix,
-            MacAddress hostMac, VlanId hostVlanId, PortNumber outPort,
-            VlanId innerVlan, EthType outerTpid,
-            boolean directHost, boolean revoke)
-            throws DeviceConfigNotFoundException {
-        int nextObjId;
-        if (directHost) {
-            // if the objective is to revoke an existing rule, and for some reason
-            // the next-objective does not exist, then a new one should not be created
-            ImmutablePair<TrafficTreatment, TrafficSelector> treatmentAndMeta =
-                    getTreatmentAndMeta(deviceId, hostMac, hostVlanId, outPort, innerVlan, outerTpid);
-            if (treatmentAndMeta == null) {
-                // Warning log will come from getTreatmentAndMeta method
-                return null;
-            }
-            nextObjId = srManager.getPortNextObjectiveId(deviceId, outPort,
-                    treatmentAndMeta.getLeft(), treatmentAndMeta.getRight(), !revoke);
-        } else {
-          // if the objective is to revoke an existing rule, and for some reason
-          // the next-objective does not exist, then a new one should not be created
-          nextObjId = srManager.getMacVlanNextObjectiveId(deviceId, hostMac, hostVlanId,
-                                          outPort, !revoke);
-        }
-        if (nextObjId == -1) {
-            // Warning log will come from getMacVlanNextObjective method
-            return null;
-        }
-
-        return DefaultForwardingObjective.builder()
-                .withSelector(buildIpSelectorFromIpPrefix(prefix).build())
-                .nextStep(nextObjId)
-                .fromApp(srManager.appId).makePermanent()
-                .withPriority(getPriorityFromPrefix(prefix))
-                .withFlag(ForwardingObjective.Flag.SPECIFIC);
-    }
-
-    private ImmutablePair<TrafficTreatment, TrafficSelector> getTreatmentAndMeta(
-            DeviceId deviceId, MacAddress hostMac, VlanId hostVlanId, PortNumber outPort,
-            VlanId innerVlan, EthType outerTpid)
-            throws DeviceConfigNotFoundException {
-        MacAddress routerMac;
-        routerMac = config.getDeviceMac(deviceId);
-
-        ConnectPoint connectPoint = new ConnectPoint(deviceId, outPort);
-        VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
-        Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
-        VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
-        // Create route treatment
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.deferred()
-                .setEthDst(hostMac)
-                .setEthSrc(routerMac)
-                .setOutput(outPort);
-
-        // Create route meta
-        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-
-        // Adjust treatment and meta according to VLAN configuration
-        if (taggedVlans.contains(hostVlanId)) {
-            tbuilder.setVlanId(hostVlanId);
-        } else if (hostVlanId.equals(VlanId.NONE)) {
-            if (untaggedVlan != null) {
-                mbuilder.matchVlanId(untaggedVlan);
-            } else if (nativeVlan != null) {
-                mbuilder.matchVlanId(nativeVlan);
-            } else {
-                log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan",
-                        hostMac, hostVlanId, connectPoint);
-                return null;
-            }
-        } else {
-            // Double tagged hosts
-            if (innerVlan == null || outerTpid == null) {
-                log.warn("Failed to construct NextObj for double tagged hosts {}/{}. {} {}",
-                        hostMac, hostVlanId,
-                        (innerVlan == null) ? "innerVlan = null." : "",
-                        (outerTpid == null) ? "outerTpid = null." : "");
-                return null;
-            }
-            tbuilder.setVlanId(innerVlan);
-            tbuilder.pushVlan(outerTpid);
-            tbuilder.setVlanId(hostVlanId);
-            mbuilder.matchVlanId(VlanId.ANY);
-        }
-
-        return ImmutablePair.of(tbuilder.build(), mbuilder.build());
-    }
-
-    /**
-     * Populates IP flow rules for all the given prefixes reachable from the
-     * destination switch(es).
-     *
-     * @param targetSw switch where rules are to be programmed
-     * @param subnets subnets/prefixes being added
-     * @param destSw1 destination switch where the prefixes are reachable
-     * @param destSw2 paired destination switch if one exists for the subnets/prefixes.
-     *                Should be null if there is no paired destination switch (by config)
-     *                or if the given prefixes are reachable only via destSw1
-     * @param nextHops a map containing a set of next-hops for each destination switch.
-     *                 If destSw2 is not null, then this map must contain an
-     *                 entry for destSw2 with its next-hops from the targetSw
-     *                 (although the next-hop set may be empty in certain scenarios).
-     *                 If destSw2 is null, there should not be an entry in this
-     *                 map for destSw2.
-     * @return true if all rules are set successfully, false otherwise
-     */
-    boolean populateIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets,
-            DeviceId destSw1, DeviceId destSw2, Map<DeviceId, Set<DeviceId>> nextHops) {
-        // Get pair device of the target switch
-        Optional<DeviceId> pairDev = srManager.getPairDeviceId(targetSw);
-        // Route simplification will be off in case of the nexthop location at target switch is down
-        // (routing through spine case)
-        boolean routeSimplOff = pairDev.isPresent() && pairDev.get().equals(destSw1) && destSw2 == null;
-        // Iterates over the routes. Checking:
-        // If route simplification is enabled
-        // If the target device is another leaf in the network
-        if (srManager.routeSimplification && !routeSimplOff) {
-            Set<IpPrefix> subnetsToBePopulated = Sets.newHashSet();
-            for (IpPrefix subnet : subnets) {
-                // Skip route programming on the target device
-                // If route simplification applies
-                if (routeSimplifierUtils.hasLeafExclusionEnabledForPrefix(subnet)) {
-                    // XXX route simplification assumes that source of the traffic
-                    // towards the nexthops are co-located with the nexthops. In different
-                    // scenarios will not work properly.
-                    continue;
-                }
-                // populate the route in the remaning scenarios
-                subnetsToBePopulated.add(subnet);
-            }
-            subnets = subnetsToBePopulated;
-        }
-        // populate the remaining routes in the target switch
-        return populateIpRulesForRouter(targetSw, subnets, destSw1, destSw2, nextHops);
-    }
-
-    /**
-     * Revokes IP flow rules for the subnets from given device.
-     *
-     * @param targetSw target switch from which the subnets need to be removed
-     * @param subnets subnet being removed
-     * @return true if all rules are removed successfully, false otherwise
-     */
-    boolean revokeIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets) {
-        for (IpPrefix subnet : subnets) {
-            if (!revokeIpRuleForRouter(targetSw, subnet)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Populates IP flow rules for a set of IP prefix in the target device.
-     * The prefix are reachable via destination device(s).
-     *
-     * @param targetSw target device ID to set the rules
-     * @param subnets the set of IP prefix
-     * @param destSw1 destination switch where the prefixes are reachable
-     * @param destSw2 paired destination switch if one exists for the subnets/prefixes.
-     *                Should be null if there is no paired destination switch (by config)
-     *                or if the given prefixes are reachable only via destSw1
-     * @param nextHops map of destination switches and their next-hops.
-     *                  Should only contain destination switches that are
-     *                  actually meant to be routed to. If destSw2 is null, there
-     *                  should not be an entry for destSw2 in this map.
-     * @return true if all rules are set successfully, false otherwise
-     */
-    private boolean populateIpRulesForRouter(DeviceId targetSw,
-                                             Set<IpPrefix> subnets,
-                                             DeviceId destSw1, DeviceId destSw2,
-                                             Map<DeviceId, Set<DeviceId>> nextHops) {
-        // pre-compute the needed information
-        int segmentIdIPv41, segmentIdIPv42 = -1;
-        int segmentIdIPv61, segmentIdIPv62 = -1;
-        TrafficTreatment treatment = null;
-        DestinationSet dsIPv4, dsIPv6;
-        TrafficSelector metaIpv4Selector, metaIpv6Selector = null;
-        int nextIdIPv4, nextIdIPv6, nextId;
-        TrafficSelector selector;
-        // start with MPLS SIDs
-        try {
-            segmentIdIPv41 = config.getIPv4SegmentId(destSw1);
-            segmentIdIPv61 = config.getIPv6SegmentId(destSw1);
-            if (destSw2 != null) {
-                segmentIdIPv42 = config.getIPv4SegmentId(destSw2);
-                segmentIdIPv62 = config.getIPv6SegmentId(destSw2);
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting populateIpRuleForRouter.");
-            return false;
-        }
-        // build the IPv4 and IPv6 destination set
-        if (destSw2 == null) {
-            // single dst - create destination set based on next-hop
-            // If the next hop is the same as the final destination, then MPLS
-            // label is not set.
-            Set<DeviceId> nhd1 = nextHops.get(destSw1);
-            if (nhd1.size() == 1 && nhd1.iterator().next().equals(destSw1)) {
-                dsIPv4 = DestinationSet.createTypePushNone(destSw1);
-                dsIPv6 = DestinationSet.createTypePushNone(destSw1);
-                treatment = DefaultTrafficTreatment.builder()
-                        .immediate()
-                        .decNwTtl()
-                        .build();
-            } else {
-                dsIPv4 = DestinationSet.createTypePushBos(segmentIdIPv41, destSw1);
-                dsIPv6 = DestinationSet.createTypePushBos(segmentIdIPv61, destSw1);
-            }
-        } else {
-            // dst pair - IP rules for dst-pairs are always from other edge nodes
-            // the destination set needs to have both destinations, even if there
-            // are no next hops to one of them
-            dsIPv4 = DestinationSet.createTypePushBos(segmentIdIPv41, destSw1, segmentIdIPv42, destSw2);
-            dsIPv6 = DestinationSet.createTypePushBos(segmentIdIPv61, destSw1, segmentIdIPv62, destSw2);
-        }
-
-        // setup metadata to pass to nextObjective - indicate the vlan on egress
-        // if needed by the switch pipeline. Since neighbor sets are always to
-        // other neighboring routers, there is no subnet assigned on those ports.
-        metaIpv4Selector = buildIpv4Selector()
-                .matchVlanId(srManager.getDefaultInternalVlan())
-                .build();
-        metaIpv6Selector = buildIpv6Selector()
-                .matchVlanId(srManager.getDefaultInternalVlan())
-                .build();
-        // get the group handler of the target switch
-        DefaultGroupHandler grpHandler = srManager.getGroupHandler(targetSw);
-        if (grpHandler == null) {
-            log.warn("populateIPRuleForRouter: groupHandler for device {} "
-                             + "not found", targetSw);
-            return false;
-        }
-        // get next id
-        nextIdIPv4 = grpHandler.getNextObjectiveId(dsIPv4, nextHops, metaIpv4Selector, false);
-        if (nextIdIPv4 <= 0) {
-            log.warn("No next objective in {} for ds: {}", targetSw, dsIPv4);
-            return false;
-        }
-        nextIdIPv6 = grpHandler.getNextObjectiveId(dsIPv6, nextHops, metaIpv6Selector, false);
-        if (nextIdIPv6 <= 0) {
-            log.warn("No next objective in {} for ds: {}", targetSw, dsIPv6);
-            return false;
-        }
-        // build all the flow rules and send to the device
-        for (IpPrefix subnet : subnets) {
-            selector = buildIpSelectorFromIpPrefix(subnet).build();
-            if (subnet.isIp4()) {
-                nextId = nextIdIPv4;
-            } else {
-                nextId = nextIdIPv6;
-            }
-            ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
-                    .builder()
-                    .fromApp(srManager.appId)
-                    .makePermanent()
-                    .nextStep(nextId)
-                    .withSelector(selector)
-                    .withPriority(getPriorityFromPrefix(subnet))
-                    .withFlag(ForwardingObjective.Flag.SPECIFIC);
-            if (treatment != null) {
-                fwdBuilder.withTreatment(treatment);
-            }
-            log.debug("Installing {} forwarding objective for router IP/subnet {} "
-                              + "in switch {} with nextId: {}", subnet.isIp4() ? "IPv4" : "IPv6",
-                      subnet, targetSw, nextId);
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("IP rule for router {} populated in dev:{}",
-                                             subnet, targetSw),
-                    (objective, error) -> log.warn("Failed to populate IP rule for router {}: {} in dev:{}",
-                                                   subnet, error, targetSw));
-            srManager.flowObjectiveService.forward(targetSw, fwdBuilder.add(context));
-        }
-        rulePopulationCounter.addAndGet(subnets.size());
-        return true;
-    }
-
-    /**
-     * Revokes IP flow rules for the router IP address from given device.
-     *
-     * @param targetSw target switch from which the ipPrefix need to be removed
-     * @param ipPrefix the IP address of the destination router
-     * @return true if all rules are removed successfully, false otherwise
-     */
-    private boolean revokeIpRuleForRouter(DeviceId targetSw, IpPrefix ipPrefix) {
-        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(ipPrefix);
-        TrafficSelector selector = sbuilder.build();
-        TrafficTreatment dummyTreatment = DefaultTrafficTreatment.builder().build();
-
-        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
-                .builder()
-                .fromApp(srManager.appId)
-                .makePermanent()
-                .withSelector(selector)
-                .withTreatment(dummyTreatment)
-                .withPriority(getPriorityFromPrefix(ipPrefix))
-                .withFlag(ForwardingObjective.Flag.SPECIFIC);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("IP rule for router {} revoked from {}", ipPrefix, targetSw),
-                (objective, error) -> log.warn("Failed to revoke IP rule for router {} from {}: {}",
-                        ipPrefix, targetSw, error));
-        srManager.flowObjectiveService.forward(targetSw, fwdBuilder.remove(context));
-
-        return true;
-    }
-
-    /**
-     * Populates MPLS flow rules in the target device to point towards the
-     * destination device.
-     *
-     * @param targetSwId target device ID of the switch to set the rules
-     * @param destSwId destination switch device ID
-     * @param nextHops next hops switch ID list
-     * @param routerIp the router ip of the destination switch
-     * @return true if all rules are set successfully, false otherwise
-     */
-    boolean populateMplsRule(DeviceId targetSwId, DeviceId destSwId,
-                             Set<DeviceId> nextHops, IpAddress routerIp) {
-        int segmentId;
-        try {
-            if (routerIp.isIp4()) {
-                segmentId = config.getIPv4SegmentId(destSwId);
-            } else {
-                segmentId = config.getIPv6SegmentId(destSwId);
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting populateMplsRule.");
-            return false;
-        }
-
-        List<ForwardingObjective> fwdObjs = new ArrayList<>();
-        Collection<ForwardingObjective> fwdObjsMpls;
-        // Generates the transit rules used by the standard "routing".
-        fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId,
-                                 routerIp, true);
-        if (fwdObjsMpls.isEmpty()) {
-            return false;
-        }
-        fwdObjs.addAll(fwdObjsMpls);
-
-        // Generates the transit rules used by the MPLS Pwaas.
-        int pwSrLabel;
-        try {
-            pwSrLabel = config.getPWRoutingLabel(destSwId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage()
-                    + " Aborting populateMplsRule. No label for PseudoWire traffic.");
-            return false;
-        }
-        fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, pwSrLabel,
-                                 routerIp, false);
-        if (fwdObjsMpls.isEmpty()) {
-            return false;
-        }
-        fwdObjs.addAll(fwdObjsMpls);
-
-        for (ForwardingObjective fwdObj : fwdObjs) {
-            log.debug("Sending MPLS fwd obj {} for SID {}-> next {} in sw: {}",
-                      fwdObj.id(), segmentId, fwdObj.nextId(), targetSwId);
-            srManager.flowObjectiveService.forward(targetSwId, fwdObj);
-            rulePopulationCounter.incrementAndGet();
-        }
-
-        return true;
-    }
-
-    /**
-     * Differentiates between popping and swapping labels when building an MPLS
-     * forwarding objective.
-     *
-     * @param targetSwId the target sw
-     * @param destSwId the destination sw
-     * @param nextHops the set of next hops
-     * @param segmentId the segmentId to match representing the destination
-     *            switch
-     * @param routerIp the router ip representing the destination switch
-     * @return a collection of fwdobjective
-     */
-    private Collection<ForwardingObjective> handleMpls(
-                                        DeviceId targetSwId,
-                                        DeviceId destSwId,
-                                        Set<DeviceId> nextHops,
-                                        int segmentId,
-                                        IpAddress routerIp,
-                                        boolean isMplsBos) {
-
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        List<ForwardingObjective.Builder> fwdObjBuilders = Lists.newArrayList();
-        // For the transport of Pwaas we can use two or three MPLS label
-        sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
-        sbuilder.matchMplsLabel(MplsLabel.mplsLabel(segmentId));
-        sbuilder.matchMplsBos(isMplsBos);
-        TrafficSelector selector = sbuilder.build();
-
-        // setup metadata to pass to nextObjective - indicate the vlan on egress
-        // if needed by the switch pipeline. Since mpls next-hops are always to
-        // other neighboring routers, there is no subnet assigned on those ports.
-        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
-        metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
-
-        if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
-            // If the next hop is the destination router for the segment, do pop
-            log.debug("populateMplsRule: Installing MPLS forwarding objective for "
-                    + "label {} in switch {} with pop to next-hops {}",
-                    segmentId, targetSwId, nextHops);
-            ForwardingObjective.Builder fwdObjNoBosBuilder =
-                    getMplsForwardingObjective(targetSwId,
-                                               nextHops,
-                                               true,
-                                               isMplsBos,
-                                               metabuilder.build(),
-                                               routerIp,
-                                               segmentId,
-                                               destSwId);
-            // Error case, we cannot handle, exit.
-            if (fwdObjNoBosBuilder == null) {
-                return Collections.emptyList();
-            }
-            fwdObjBuilders.add(fwdObjNoBosBuilder);
-
-        } else {
-            // next hop is not destination, irrespective of the number of next
-            // hops (1 or more) -- SR CONTINUE case (swap with self)
-            log.debug("Installing MPLS forwarding objective for "
-                    + "label {} in switch {} without pop to next-hops {}",
-                    segmentId, targetSwId, nextHops);
-            ForwardingObjective.Builder fwdObjNoBosBuilder =
-                    getMplsForwardingObjective(targetSwId,
-                                               nextHops,
-                                               false,
-                                               isMplsBos,
-                                               metabuilder.build(),
-                                               routerIp,
-                                               segmentId,
-                                               destSwId);
-            // Error case, we cannot handle, exit.
-            if (fwdObjNoBosBuilder == null) {
-                return Collections.emptyList();
-            }
-            fwdObjBuilders.add(fwdObjNoBosBuilder);
-
-        }
-
-        List<ForwardingObjective> fwdObjs = Lists.newArrayList();
-        // We add the final property to the fwdObjs.
-        for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
-            ((Builder) ((Builder) fwdObjBuilder
-                    .fromApp(srManager.appId)
-                    .makePermanent())
-                    .withSelector(selector)
-                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY))
-                    .withFlag(ForwardingObjective.Flag.SPECIFIC);
-
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) ->
-                            log.debug("MPLS rule {} for SID {} populated in dev:{} ",
-                                      objective.id(), segmentId, targetSwId),
-                    (objective, error) ->
-                            log.warn("Failed to populate MPLS rule {} for SID {}: {} in dev:{}",
-                                     objective.id(), segmentId, error, targetSwId));
-
-            ForwardingObjective fob = fwdObjBuilder.add(context);
-            fwdObjs.add(fob);
-        }
-
-        return fwdObjs;
-    }
-
-    /**
-     * Returns a Forwarding Objective builder for the MPLS rule that references
-     * the desired Next Objective. Creates a DestinationSet that allows the
-     * groupHandler to create or find the required next objective.
-     *
-     * @param targetSw the target sw
-     * @param nextHops the set of next hops
-     * @param phpRequired true if penultimate-hop-popping is required
-     * @param isBos true if matched label is bottom-of-stack
-     * @param meta metadata for creating next objective
-     * @param routerIp the router ip representing the destination switch
-     * @param destSw the destination sw
-     * @return the mpls forwarding objective builder
-     */
-    private ForwardingObjective.Builder getMplsForwardingObjective(
-                                             DeviceId targetSw,
-                                             Set<DeviceId> nextHops,
-                                             boolean phpRequired,
-                                             boolean isBos,
-                                             TrafficSelector meta,
-                                             IpAddress routerIp,
-                                             int segmentId,
-                                             DeviceId destSw) {
-
-        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
-                .builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
-
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        DestinationSet ds = null;
-        DestinationSet.DestinationSetType dstType = null;
-        boolean simple = false;
-        if (phpRequired) {
-            // php case - pop should always be flow-action
-            log.debug("getMplsForwardingObjective: php required");
-            tbuilder.deferred().copyTtlIn();
-            if (isBos) {
-                if (routerIp.isIp4()) {
-                    tbuilder.deferred().popMpls(EthType.EtherType.IPV4.ethType());
-                } else {
-                    tbuilder.deferred().popMpls(EthType.EtherType.IPV6.ethType());
-                }
-                tbuilder.decNwTtl();
-                // standard case -> BoS == True; pop results in IP packet and forwarding
-                // is via an ECMP group
-                ds = DestinationSet.createTypePopBos(destSw);
-            } else {
-                tbuilder.deferred().popMpls(EthType.EtherType.MPLS_UNICAST.ethType())
-                    .decMplsTtl();
-                // double-label case -> BoS == False, pop results in MPLS packet
-                // depending on configuration we can ECMP this packet or choose one output
-                ds = DestinationSet.createTypePopNotBos(destSw);
-                if (!srManager.getMplsEcmp()) {
-                   simple = true;
-                }
-            }
-        } else {
-            // swap with self case - SR CONTINUE
-            log.debug("getMplsForwardingObjective: swap with self");
-            tbuilder.deferred().decMplsTtl();
-            // swap results in MPLS packet with same BoS bit regardless of bit value
-            // depending on configuration we can ECMP this packet or choose one output
-            // differentiate here between swap with not bos or swap with bos
-            ds = isBos ? DestinationSet.createTypeSwapBos(segmentId, destSw) :
-                    DestinationSet.createTypeSwapNotBos(segmentId, destSw);
-            if (!srManager.getMplsEcmp()) {
-                simple = true;
-            }
-        }
-
-        fwdBuilder.withTreatment(tbuilder.build());
-        log.debug("Trying to get a nextObjId for mpls rule on device:{} to ds:{}",
-                  targetSw, ds);
-        DefaultGroupHandler gh = srManager.getGroupHandler(targetSw);
-        if (gh == null) {
-            log.warn("getNextObjectiveId query - groupHandler for device {} "
-                    + "not found", targetSw);
-            return null;
-        }
-
-        Map<DeviceId, Set<DeviceId>> dstNextHops = new HashMap<>();
-        dstNextHops.put(destSw, nextHops);
-        int nextId = gh.getNextObjectiveId(ds, dstNextHops, meta, simple);
-        if (nextId <= 0) {
-            log.warn("No next objective in {} for ds: {}", targetSw, ds);
-            return null;
-        } else {
-            log.debug("nextObjId found:{} for mpls rule on device:{} to ds:{}",
-                      nextId, targetSw, ds);
-        }
-
-        fwdBuilder.nextStep(nextId);
-        return fwdBuilder;
-    }
-
-    /**
-     * Creates a filtering objective to permit all untagged packets with a
-     * dstMac corresponding to the router's MAC address. For those pipelines
-     * that need to internally assign vlans to untagged packets, this method
-     * provides per-subnet vlan-ids as metadata.
-     * <p>
-     * Note that the vlan assignment and filter programming should only be done by
-     * the master for a switch. This method is typically called at deviceAdd and
-     * programs filters only for the enabled ports of the device. For port-updates,
-     * that enable/disable ports after device add, singlePortFilter methods should
-     * be called.
-     *
-     * @param deviceId  the switch dpid for the router
-     * @return PortFilterInfo information about the processed ports
-     */
-    PortFilterInfo populateVlanMacFilters(DeviceId deviceId) {
-        log.debug("Installing per-port filtering objective for untagged "
-                + "packets in device {}", deviceId);
-
-        List<Port> devPorts = srManager.deviceService.getPorts(deviceId);
-        if (devPorts == null || devPorts.isEmpty()) {
-            log.warn("Device {} ports not available. Unable to add MacVlan filters",
-                     deviceId);
-            return null;
-        }
-        int disabledPorts = 0, errorPorts = 0, filteredPorts = 0;
-        for (Port port : devPorts) {
-            if (!port.isEnabled()) {
-                disabledPorts++;
-                continue;
-            }
-            if (processSinglePortFilters(deviceId, port.number(), true)) {
-                filteredPorts++;
-            } else {
-                errorPorts++;
-            }
-        }
-        log.debug("Filtering on dev:{}, disabledPorts:{}, errorPorts:{}, filteredPorts:{}",
-                  deviceId, disabledPorts, errorPorts, filteredPorts);
-        return new PortFilterInfo(disabledPorts, errorPorts, filteredPorts);
-    }
-
-    /**
-     * Creates or removes filtering objectives for a single port. Should only be
-     * called by the master for a switch.
-     *
-     * @param deviceId device identifier
-     * @param portnum  port identifier for port to be filtered
-     * @param install true to install the filtering objective, false to remove
-     * @return true if no errors occurred during the build of the filtering objective
-     */
-    boolean processSinglePortFilters(DeviceId deviceId, PortNumber portnum, boolean install) {
-        ConnectPoint connectPoint = new ConnectPoint(deviceId, portnum);
-        VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
-        Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
-        VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
-        // Do not configure filter for edge ports where double-tagged hosts are connected.
-        if (taggedVlans.size() != 0) {
-            // Filter for tagged vlans
-            if (!srManager.interfaceService.getTaggedVlanId(connectPoint).stream().allMatch(taggedVlanId ->
-                    processSinglePortFiltersInternal(deviceId, portnum, false, taggedVlanId, install))) {
-                return false;
-            }
-            if (nativeVlan != null) {
-                // Filter for native vlan
-                if (!processSinglePortFiltersInternal(deviceId, portnum, true, nativeVlan, install)) {
-                    return false;
-                }
-            }
-        } else if (untaggedVlan != null) {
-            // Filter for untagged vlan
-            if (!processSinglePortFiltersInternal(deviceId, portnum, true, untaggedVlan, install)) {
-                return false;
-            }
-        } else if (!hasIPConfiguration(connectPoint)) {
-            // Filter for unconfigured upstream port, using INTERNAL_VLAN
-            if (!processSinglePortFiltersInternal(deviceId, portnum, true,
-                                                  srManager.getDefaultInternalVlan(),
-                                                  install)) {
-                return false;
-            }
-            // Filter for receiveing pseudowire traffic
-            if (!processSinglePortFiltersInternal(deviceId, portnum, false,
-                                                  srManager.getPwTransportVlan(),
-                                                  install)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Updates filtering objectives for a single port. Should only be called by
-     * the master for a switch
-     * @param deviceId device identifier
-     * @param portNum  port identifier for port to be filtered
-     * @param pushVlan true to push vlan, false otherwise
-     * @param vlanId vlan identifier
-     * @param install true to install the filtering objective, false to remove
-     */
-    void updateSinglePortFilters(DeviceId deviceId, PortNumber portNum,
-                                 boolean pushVlan, VlanId vlanId, boolean install) {
-        if (!processSinglePortFiltersInternal(deviceId, portNum, pushVlan, vlanId, install)) {
-            log.warn("Failed to update FilteringObjective for {}/{} with vlan {}",
-                     deviceId, portNum, vlanId);
-        }
-    }
-
-    private boolean processSinglePortFiltersInternal(DeviceId deviceId, PortNumber portnum,
-                                                      boolean pushVlan, VlanId vlanId, boolean install) {
-        boolean doTMAC = true;
-
-        if (!pushVlan) {
-            // Skip the tagged vlans belonging to an interface without an IP address
-            Set<Interface> ifaces = srManager.interfaceService
-                    .getInterfacesByPort(new ConnectPoint(deviceId, portnum))
-                    .stream()
-                    .filter(intf -> intf.vlanTagged().contains(vlanId) && intf.ipAddressesList().isEmpty())
-                    .collect(Collectors.toSet());
-            if (!ifaces.isEmpty()) {
-                log.debug("processSinglePortFiltersInternal: skipping TMAC for vlan {} at {}/{} - no IP",
-                          vlanId, deviceId, portnum);
-                doTMAC = false;
-            }
-        }
-
-        FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum, pushVlan, vlanId, doTMAC);
-        if (fob == null) {
-            // error encountered during build
-            return false;
-        }
-        log.debug("{} filtering objectives for dev/port: {}/{}",
-                 install ? "Installing" : "Removing", deviceId, portnum);
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Filter for {}/{} {}", deviceId, portnum,
-                        install ? "installed" : "removed"),
-                (objective, error) -> log.warn("Failed to {} filter for {}/{}: {}",
-                        install ? "install" : "remove", deviceId, portnum, error));
-        if (install) {
-            srManager.flowObjectiveService.filter(deviceId, fob.add(context));
-        } else {
-            srManager.flowObjectiveService.filter(deviceId, fob.remove(context));
-        }
-        return true;
-    }
-
-    private FilteringObjective.Builder buildFilteringObjective(DeviceId deviceId, PortNumber portnum,
-                                                               boolean pushVlan, VlanId vlanId, boolean doTMAC) {
-        MacAddress deviceMac;
-        try {
-            deviceMac = config.getDeviceMac(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Processing SinglePortFilters aborted");
-            return null;
-        }
-        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
-
-        if (doTMAC) {
-            fob.withKey(Criteria.matchInPort(portnum))
-                    .addCondition(Criteria.matchEthDst(deviceMac))
-                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
-        } else {
-            fob.withKey(Criteria.matchInPort(portnum))
-                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
-        }
-
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
-        if (pushVlan) {
-            fob.addCondition(Criteria.matchVlanId(VlanId.NONE));
-            tBuilder.pushVlan().setVlanId(vlanId);
-        } else {
-            fob.addCondition(Criteria.matchVlanId(vlanId));
-        }
-
-        // NOTE: Some switch hardware share the same filtering flow among different ports.
-        //       We use this metadata to let the driver know that there is no more enabled port
-        //       within the same VLAN on this device.
-        if (noMoreEnabledPort(deviceId, vlanId)) {
-            tBuilder.wipeDeferred();
-        }
-
-        fob.withMeta(tBuilder.build());
-
-        fob.permit().fromApp(srManager.appId);
-        return fob;
-    }
-
-    /**
-     * Creates or removes filtering objectives for a double-tagged host on a port.
-     *
-     * @param deviceId device identifier
-     * @param portNum  port identifier for port to be filtered
-     * @param outerVlan outer VLAN ID
-     * @param innerVlan inner VLAN ID
-     * @param install true to install the filtering objective, false to remove
-     */
-    void processDoubleTaggedFilter(DeviceId deviceId, PortNumber portNum, VlanId outerVlan,
-                                   VlanId innerVlan, boolean install) {
-        // We should trigger the removal of double tagged rules only when removing
-        // the filtering objective and no other hosts are connected to the same device port.
-        boolean cleanupDoubleTaggedRules = !anyDoubleTaggedHost(deviceId, portNum) && !install;
-        FilteringObjective.Builder fob = buildDoubleTaggedFilteringObj(deviceId, portNum,
-                                                                       outerVlan, innerVlan,
-                                                                       cleanupDoubleTaggedRules);
-        if (fob == null) {
-            // error encountered during build
-            return;
-        }
-        log.debug("{} double-tagged filtering objectives for dev/port: {}/{}",
-                  install ? "Installing" : "Removing", deviceId, portNum);
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Filter for {}/{} {}", deviceId, portNum,
-                                         install ? "installed" : "removed"),
-                (objective, error) -> log.warn("Failed to {} filter for {}/{}: {}",
-                                               install ? "install" : "remove", deviceId, portNum, error));
-        if (install) {
-            srManager.flowObjectiveService.filter(deviceId, fob.add(context));
-        } else {
-            srManager.flowObjectiveService.filter(deviceId, fob.remove(context));
-        }
-    }
-
-    /**
-     * Checks if there is any double tagged host attached to given location.
-     * This method will match on the effective location of a host.
-     * That is, it will match on auxLocations when auxLocations is not null. Otherwise, it will match on locations.
-     *
-     * @param deviceId device ID
-     * @param portNum port number
-     * @return true if there is any host attached to given location.
-     */
-    private boolean anyDoubleTaggedHost(DeviceId deviceId, PortNumber portNum) {
-        ConnectPoint cp = new ConnectPoint(deviceId, portNum);
-        Set<Host> connectedHosts = srManager.hostService.getConnectedHosts(cp, false);
-        Set<Host> auxConnectedHosts = srManager.hostService.getConnectedHosts(cp, true);
-        return !auxConnectedHosts.isEmpty() ||
-                connectedHosts.stream().anyMatch(host -> host.auxLocations() == null);
-    }
-
-    private FilteringObjective.Builder buildDoubleTaggedFilteringObj(DeviceId deviceId, PortNumber portNum,
-                                                                     VlanId outerVlan, VlanId innerVlan,
-                                                                     boolean cleanupDoubleTaggedRules) {
-        MacAddress deviceMac;
-        try {
-            deviceMac = config.getDeviceMac(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Processing DoubleTaggedFilters aborted");
-            return null;
-        }
-        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
-        // Outer vlan id match should be appeared before inner vlan id match.
-        fob.withKey(Criteria.matchInPort(portNum))
-                .addCondition(Criteria.matchEthDst(deviceMac))
-                .addCondition(Criteria.matchVlanId(outerVlan))
-                .addCondition(Criteria.matchInnerVlanId(innerVlan))
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
-
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        // Pop outer vlan
-        tBuilder.popVlan();
-
-        // special metadata for driver
-        if (cleanupDoubleTaggedRules) {
-            tBuilder.writeMetadata(CLEANUP_DOUBLE_TAGGED_HOST_ENTRIES, DOUBLE_TAGGED_METADATA_MASK);
-        } else {
-            tBuilder.writeMetadata(0, DOUBLE_TAGGED_METADATA_MASK);
-        }
-
-        // NOTE: Some switch hardware share the same filtering flow among different ports.
-        //       We use this metadata to let the driver know that there is no more enabled port
-        //       within the same VLAN on this device.
-        if (noMoreEnabledPort(deviceId, outerVlan)) {
-            tBuilder.wipeDeferred();
-        }
-
-        fob.withMeta(tBuilder.build());
-
-        fob.permit().fromApp(srManager.appId);
-        return fob;
-    }
-
-    /**
-     * Creates a forwarding objective to punt all IP packets, destined to the
-     * router's port IP addresses, to the controller. Note that the input
-     * port should not be matched on, as these packets can come from any input.
-     * Furthermore, these are applied only by the master instance.
-     *
-     * @param deviceId the switch dpid for the router
-     */
-    void populateIpPunts(DeviceId deviceId) {
-        Ip4Address routerIpv4, pairRouterIpv4 = null;
-        Ip6Address routerIpv6, routerLinkLocalIpv6, pairRouterIpv6 = null;
-        try {
-            routerIpv4 = config.getRouterIpv4(deviceId);
-            routerIpv6 = config.getRouterIpv6(deviceId);
-            routerLinkLocalIpv6 = Ip6Address.valueOf(
-                    IPv6.getLinkLocalAddress(config.getDeviceMac(deviceId).toBytes()));
-
-            if (config.isPairedEdge(deviceId)) {
-                pairRouterIpv4 = config.getRouterIpv4(config.getPairDeviceId(deviceId));
-                pairRouterIpv6 = config.getRouterIpv6(config.getPairDeviceId(deviceId));
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting populateIpPunts.");
-            return;
-        }
-
-        if (!srManager.mastershipService.isLocalMaster(deviceId)) {
-            log.debug("Not installing port-IP punts - not the master for dev:{} ",
-                      deviceId);
-            return;
-        }
-        Set<IpAddress> allIps = new HashSet<>(config.getPortIPs(deviceId));
-        allIps.add(routerIpv4);
-        if (routerIpv6 != null) {
-            allIps.add(routerIpv6);
-            allIps.add(routerLinkLocalIpv6);
-        }
-        if (pairRouterIpv4 != null) {
-            allIps.add(pairRouterIpv4);
-        }
-        if (pairRouterIpv6 != null) {
-            allIps.add(pairRouterIpv6);
-        }
-        for (IpAddress ipaddr : allIps) {
-            populateSingleIpPunts(deviceId, ipaddr);
-        }
-    }
-
-    /**
-     * Creates a forwarding objective to punt all IP packets, destined to the
-     * specified IP address, which should be router's port IP address.
-     *
-     * @param deviceId the switch dpid for the router
-     * @param ipAddress the IP address of the router's port
-     */
-    void populateSingleIpPunts(DeviceId deviceId, IpAddress ipAddress) {
-        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipAddress);
-        Optional<DeviceId> optDeviceId = Optional.of(deviceId);
-
-        srManager.packetService.requestPackets(sbuilder.build(),
-                                               PacketPriority.CONTROL, srManager.appId, optDeviceId);
-    }
-
-    /**
-     * Removes a forwarding objective to punt all IP packets, destined to the
-     * specified IP address, which should be router's port IP address.
-     *
-     * @param deviceId the switch dpid for the router
-     * @param ipAddress the IP address of the router's port
-     */
-    void revokeSingleIpPunts(DeviceId deviceId, IpAddress ipAddress) {
-        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipAddress);
-        Optional<DeviceId> optDeviceId = Optional.of(deviceId);
-
-        try {
-            if (!ipAddress.equals(config.getRouterIpv4(deviceId)) &&
-                    !ipAddress.equals(config.getRouterIpv6(deviceId))) {
-                srManager.packetService.cancelPackets(sbuilder.build(),
-                                                      PacketPriority.CONTROL, srManager.appId, optDeviceId);
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting revokeSingleIpPunts");
-        }
-    }
-
-    // Method for building an IPv4 selector
-    private TrafficSelector.Builder buildIpv4Selector() {
-        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
-        return selectorBuilder;
-    }
-
-    // Method for building an IPv6 selector
-    private TrafficSelector.Builder buildIpv6Selector() {
-        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
-        return selectorBuilder;
-    }
-
-    // Method for building an IPv4 or IPv6 selector from an IP address
-    private TrafficSelector.Builder buildIpSelectorFromIpAddress(IpAddress addressToMatch) {
-        return buildIpSelectorFromIpPrefix(addressToMatch.toIpPrefix());
-    }
-
-    // Method for building an IPv4 or IPv6 selector from an IP prefix
-    private TrafficSelector.Builder buildIpSelectorFromIpPrefix(IpPrefix prefixToMatch) {
-        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
-        // If the prefix is IPv4
-        if (prefixToMatch.isIp4()) {
-            selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
-            selectorBuilder.matchIPDst(prefixToMatch.getIp4Prefix());
-            return selectorBuilder;
-        }
-        // If the prefix is IPv6
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
-        selectorBuilder.matchIPv6Dst(prefixToMatch.getIp6Prefix());
-        return selectorBuilder;
-    }
-
-    /**
-     * Creates forwarding objectives to punt ARP and NDP packets, to the controller.
-     * Furthermore, these are applied only by the master instance. Deferred actions
-     * are not cleared such that packets can be flooded in the cross connect use case
-     *
-     * @param deviceId the switch dpid for the router
-     */
-    void populateArpNdpPunts(DeviceId deviceId) {
-        // We are not the master just skip.
-        if (!srManager.mastershipService.isLocalMaster(deviceId)) {
-            log.debug("Not installing ARP/NDP punts - not the master for dev:{} ",
-                      deviceId);
-            return;
-        }
-
-        ForwardingObjective fwdObj;
-        // We punt all ARP packets towards the controller.
-        fwdObj = arpFwdObjective(null, true, ARP_NDP_PRIORITY)
-                .add(new ObjectiveContext() {
-                    @Override
-                    public void onError(Objective objective, ObjectiveError error) {
-                        log.warn("Failed to install forwarding objective to punt ARP to {}: {}",
-                                 deviceId, error);
-                    }
-                });
-        srManager.flowObjectiveService.forward(deviceId, fwdObj);
-
-        if (isIpv6Configured(deviceId)) {
-            // We punt all NDP packets towards the controller.
-            ndpFwdObjective(null, true, ARP_NDP_PRIORITY).forEach(builder -> {
-                 ForwardingObjective obj = builder.add(new ObjectiveContext() {
-                    @Override
-                    public void onError(Objective objective, ObjectiveError error) {
-                        log.warn("Failed to install forwarding objective to punt NDP to {}: {}",
-                                deviceId, error);
-                    }
-                });
-                srManager.flowObjectiveService.forward(deviceId, obj);
-            });
-        }
-
-        srManager.getPairLocalPort(deviceId).ifPresent(port -> {
-            ForwardingObjective pairFwdObj;
-            // Do not punt ARP packets from pair port
-            pairFwdObj = arpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1)
-                    .add(new ObjectiveContext() {
-                        @Override
-                        public void onError(Objective objective, ObjectiveError error) {
-                            log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
-                                    deviceId, error);
-                        }
-                    });
-            srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
-
-            if (isIpv6Configured(deviceId)) {
-                // Do not punt NDP packets from pair port
-                ndpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1).forEach(builder -> {
-                    ForwardingObjective obj = builder.add(new ObjectiveContext() {
-                        @Override
-                        public void onError(Objective objective, ObjectiveError error) {
-                            log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
-                                    deviceId, error);
-                        }
-                    });
-                    srManager.flowObjectiveService.forward(deviceId, obj);
-                });
-
-                // Do not forward DAD packets from pair port
-                pairFwdObj = dad6FwdObjective(port, PacketPriority.CONTROL.priorityValue() + 2)
-                        .add(new ObjectiveContext() {
-                            @Override
-                            public void onError(Objective objective, ObjectiveError error) {
-                                log.warn("Failed to install forwarding objective to drop DAD to {}: {}",
-                                        deviceId, error);
-                            }
-                        });
-                srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
-            }
-        });
-    }
-
-    private ForwardingObjective.Builder fwdObjBuilder(TrafficSelector selector,
-                                                      TrafficTreatment treatment, int priority) {
-        return DefaultForwardingObjective.builder()
-                .withPriority(priority)
-                .withSelector(selector)
-                .fromApp(srManager.appId)
-                .withFlag(ForwardingObjective.Flag.VERSATILE)
-                .withTreatment(treatment)
-                .makePermanent();
-    }
-
-    private ForwardingObjective.Builder arpFwdObjective(PortNumber port, boolean punt, int priority) {
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-        sBuilder.matchEthType(TYPE_ARP);
-        if (port != null) {
-            sBuilder.matchInPort(port);
-        }
-
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        if (punt) {
-            tBuilder.punt();
-        }
-        return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
-    }
-
-    private Set<ForwardingObjective.Builder> ndpFwdObjective(PortNumber port, boolean punt, int priority) {
-        Set<ForwardingObjective.Builder> result = Sets.newHashSet();
-
-        Lists.newArrayList(NEIGHBOR_SOLICITATION, NEIGHBOR_ADVERTISEMENT, ROUTER_SOLICITATION, ROUTER_ADVERTISEMENT)
-                .forEach(type -> {
-                    TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-                    sBuilder.matchEthType(TYPE_IPV6)
-                            .matchIPProtocol(PROTOCOL_ICMP6)
-                            .matchIcmpv6Type(type);
-                    if (port != null) {
-                        sBuilder.matchInPort(port);
-                    }
-
-                    TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-                    if (punt) {
-                        tBuilder.punt();
-                    }
-
-                    result.add(fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority));
-                });
-
-        return result;
-    }
-
-    private ForwardingObjective.Builder dad6FwdObjective(PortNumber port, int priority) {
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-        sBuilder.matchEthType(TYPE_IPV6)
-                .matchIPv6Src(Ip6Address.ZERO.toIpPrefix());
-                // TODO CORD-1672 Fix this when OFDPA can distinguish ::/0 and ::/128 correctly
-                // .matchIPProtocol(PROTOCOL_ICMP6)
-                // .matchIcmpv6Type(NEIGHBOR_SOLICITATION);
-        if (port != null) {
-            sBuilder.matchInPort(port);
-        }
-
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        tBuilder.wipeDeferred();
-        return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
-    }
-
-    /**
-     * Block given prefix in routing table.
-     *
-     * @param address the address to block
-     * @param deviceId switch ID to set the rules
-     */
-    void populateDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address) {
-        updateDefaultRouteBlackhole(deviceId, address, true);
-    }
-
-    /**
-     * Unblock given prefix in routing table.
-     *
-     * @param address the address to block
-     * @param deviceId switch ID to set the rules
-     */
-    void removeDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address) {
-        updateDefaultRouteBlackhole(deviceId, address, false);
-    }
-
-    private void updateDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address, boolean install) {
-        try {
-            if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {
-
-                TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-                if (address.isIp4()) {
-                    sbuilder.matchIPDst(address);
-                    sbuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort());
-                } else {
-                    sbuilder.matchIPv6Dst(address);
-                    sbuilder.matchEthType(EthType.EtherType.IPV6.ethType().toShort());
-                }
-
-                TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-                tBuilder.wipeDeferred();
-
-                ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
-                fob.withFlag(Flag.SPECIFIC)
-                        .withSelector(sbuilder.build())
-                        .withTreatment(tBuilder.build())
-                        .withPriority(getPriorityFromPrefix(address))
-                        .fromApp(srManager.appId)
-                        .makePermanent();
-
-                log.debug("{} blackhole forwarding objectives for dev: {}",
-                        install ? "Installing" : "Removing", deviceId);
-                ObjectiveContext context = new DefaultObjectiveContext(
-                        (objective) -> log.debug("Forward for {} {}", deviceId,
-                                install ? "installed" : "removed"),
-                        (objective, error) -> log.warn("Failed to {} forward for {}: {}",
-                                install ? "install" : "remove", deviceId, error));
-                if (install) {
-                    srManager.flowObjectiveService.forward(deviceId, fob.add(context));
-                } else {
-                    srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
-                }
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.info("Not populating blackhole for un-configured device {}", deviceId);
-        }
-
-    }
-
-    /**
-     * Populates a forwarding objective to send packets that miss other high
-     * priority Bridging Table entries to a group that contains all ports of
-     * its subnet.
-     *
-     * @param deviceId switch ID to set the rules
-     */
-    void populateSubnetBroadcastRule(DeviceId deviceId) {
-        srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
-            updateSubnetBroadcastRule(deviceId, vlanId, true);
-        });
-    }
-
-    /**
-     * Creates or removes a forwarding objective to broadcast packets to its subnet.
-     * @param deviceId switch ID to set the rule
-     * @param vlanId vlan ID to specify the subnet
-     * @param install true to install the rule, false to revoke the rule
-     */
-    void updateSubnetBroadcastRule(DeviceId deviceId, VlanId vlanId, boolean install) {
-        int nextId = srManager.getVlanNextObjectiveId(deviceId, vlanId);
-
-        if (nextId < 0) {
-            log.error("Cannot install vlan {} broadcast rule in dev:{} due"
-                              + " to vlanId:{} or nextId:{}", vlanId, deviceId, vlanId, nextId);
-            return;
-        }
-
-        // Driver should treat objective with MacAddress.NONE as the
-        // subnet broadcast rule
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        sbuilder.matchVlanId(vlanId);
-        sbuilder.matchEthDst(MacAddress.NONE);
-
-        ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
-        fob.withFlag(Flag.SPECIFIC)
-                .withSelector(sbuilder.build())
-                .nextStep(nextId)
-                .withPriority(SegmentRoutingService.FLOOD_PRIORITY)
-                .fromApp(srManager.appId)
-                .makePermanent();
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Vlan broadcast rule for {} populated", vlanId),
-                (objective, error) ->
-                        log.warn("Failed to populate vlan broadcast rule for {}: {}", vlanId, error));
-
-        if (install) {
-            srManager.flowObjectiveService.forward(deviceId, fob.add(context));
-        } else {
-            srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
-        }
-    }
-
-    private int getPriorityFromPrefix(IpPrefix prefix) {
-        return (prefix.isIp4()) ?
-                2000 * prefix.prefixLength() + SegmentRoutingService.MIN_IP_PRIORITY :
-                500 * prefix.prefixLength() + SegmentRoutingService.MIN_IP_PRIORITY;
-    }
-
-    /**
-     * Update Forwarding objective for each host and IP address connected to given port.
-     * And create corresponding Simple Next objective if it does not exist.
-     * Applied only when populating Forwarding objective
-     * @param deviceId switch ID to set the rule
-     * @param portNumber port number
-     * @param prefix IP prefix of the route
-     * @param hostMac MAC address of the next hop
-     * @param vlanId Vlan ID of the port
-     * @param popVlan true to pop vlan tag in TrafficTreatment
-     * @param install true to populate the forwarding objective, false to revoke
-     */
-    void updateFwdObj(DeviceId deviceId, PortNumber portNumber, IpPrefix prefix, MacAddress hostMac,
-                      VlanId vlanId, boolean popVlan, boolean install) {
-        ForwardingObjective.Builder fob;
-        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(prefix);
-        MacAddress deviceMac;
-        try {
-            deviceMac = config.getDeviceMac(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting updateFwdObj.");
-            return;
-        }
-
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.deferred()
-                .setEthDst(hostMac)
-                .setEthSrc(deviceMac)
-                .setOutput(portNumber);
-
-        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-
-        if (!popVlan) {
-            tbuilder.setVlanId(vlanId);
-        } else {
-            mbuilder.matchVlanId(vlanId);
-        }
-
-        // if the objective is to revoke an existing rule, and for some reason
-        // the next-objective does not exist, then a new one should not be created
-        int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNumber,
-                                                             tbuilder.build(), mbuilder.build(), install);
-        if (portNextObjId == -1) {
-            // Warning log will come from getPortNextObjective method
-            return;
-        }
-
-        fob = DefaultForwardingObjective.builder().withSelector(sbuilder.build())
-                .nextStep(portNextObjId).fromApp(srManager.appId).makePermanent()
-                .withPriority(getPriorityFromPrefix(prefix)).withFlag(ForwardingObjective.Flag.SPECIFIC);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("IP rule for route {} {}", prefix, install ? "installed" : "revoked"),
-                (objective, error) ->
-                        log.warn("Failed to {} IP rule for route {}: {}",
-                                 install ? "install" : "revoke", prefix, error));
-        srManager.flowObjectiveService.forward(deviceId, install ? fob.add(context) : fob.remove(context));
-
-        if (!install) {
-            if (!srManager.getVlanPortMap(deviceId).containsKey(vlanId) ||
-                    !srManager.getVlanPortMap(deviceId).get(vlanId).contains(portNumber)) {
-                DefaultGroupHandler grpHandler = srManager.getGroupHandler(deviceId);
-                if (grpHandler == null) {
-                    log.warn("updateFwdObj: groupHandler for device {} not found", deviceId);
-                } else {
-                    // Remove L3UG for the given port and host
-                    grpHandler.removeGroupFromPort(portNumber, tbuilder.build(), mbuilder.build());
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks if there is other enabled port within the given VLAN on the given device.
-     *
-     * @param deviceId device ID
-     * @param vlanId VLAN ID
-     * @return true if there is no more port enabled within the given VLAN on the given device
-     */
-    boolean noMoreEnabledPort(DeviceId deviceId, VlanId vlanId) {
-        Set<ConnectPoint> enabledPorts = srManager.deviceService.getPorts(deviceId).stream()
-                .filter(Port::isEnabled)
-                .map(port -> new ConnectPoint(port.element().id(), port.number()))
-                .collect(Collectors.toSet());
-
-        return enabledPorts.stream().noneMatch(cp ->
-            // Given vlanId is included in the vlan-tagged configuration
-            srManager.interfaceService.getTaggedVlanId(cp).contains(vlanId) ||
-            // Given vlanId is INTERNAL_VLAN or PSEUDOWIRE_VLAN and the interface is not configured
-            (srManager.interfaceService.getTaggedVlanId(cp).isEmpty() && srManager.getInternalVlanId(cp) == null &&
-                (vlanId.equals(srManager.getDefaultInternalVlan()) || vlanId.equals(srManager.getPwTransportVlan()))) ||
-            // interface is configured and either vlan-untagged or vlan-native matches given vlanId
-            (srManager.getInternalVlanId(cp) != null && srManager.getInternalVlanId(cp).equals(vlanId))
-        );
-    }
-
-    /**
-     * Returns a forwarding objective builder for egress forwarding rules.
-     * <p>
-     * The forwarding objective installs flow rules to egress pipeline to push
-     * two vlan headers with given inner, outer vlan ids and outer tpid.
-     *
-     * @param portNumber port where the next hop attaches to
-     * @param dummyVlanId vlan ID of the packet to match
-     * @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
-     * @return forwarding objective builder
-     */
-    private ForwardingObjective.Builder egressFwdObjBuilder(PortNumber portNumber, VlanId dummyVlanId,
-                                                            VlanId innerVlan, VlanId outerVlan, EthType outerTpid) {
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        sbuilder.matchVlanId(dummyVlanId);
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.setOutput(portNumber).setVlanId(innerVlan);
-
-        if (outerTpid.equals(EthType.EtherType.QINQ.ethType())) {
-            tbuilder.pushVlan(outerTpid);
-        } else {
-            tbuilder.pushVlan();
-        }
-
-        tbuilder.setVlanId(outerVlan);
-        return DefaultForwardingObjective.builder()
-                .withSelector(sbuilder.build())
-                .withTreatment(tbuilder.build())
-                .fromApp(srManager.appId)
-                .makePermanent()
-                .withPriority(DEFAULT_PRIORITY)
-                .withFlag(ForwardingObjective.Flag.EGRESS);
-    }
-
-    /**
-     * Populates IP rules for a route that has double-tagged next hop.
-     *
-     * @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 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 where the next hop attaches to
-     */
-    void populateDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
-                                   VlanId innerVlan, VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
-        ForwardingObjective.Builder fwdBuilder;
-        log.debug("Populate direct routing entry for double-tagged host route {} at {}:{}",
-                  prefix, deviceId, outPort);
-
-        try {
-            fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac, outerVlan, outPort, innerVlan, outerTpid,
-                    true, false);
-        } catch (DeviceConfigNotFoundException e) {
-            log.error(e.getMessage() + " Aborting populateDoubleTaggedRoute");
-            return;
-        }
-        if (fwdBuilder == null) {
-            log.error("Aborting double-tagged host routing table entry due to error for dev:{} route:{}",
-                     deviceId, prefix);
-            return;
-        }
-
-        int nextId = fwdBuilder.add().nextId();
-        DefaultObjectiveContext context = new DefaultObjectiveContext(objective -> {
-            log.debug("Direct routing rule for double-tagged host route {} populated. nextId={}", prefix, nextId);
-        }, (objective, error) ->
-            log.warn("Failed to populate direct routing rule for double-tagged host route {}: {}", prefix, error)
-        );
-        srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
-        rulePopulationCounter.incrementAndGet();
-    }
-
-    /**
-     * Revokes IP rules for a route that has double-tagged next hop.
-     *
-     * @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 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 where the next hop attaches to
-     */
-    void revokeDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
-                                 VlanId innerVlan, VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
-        ForwardingObjective.Builder fwdBuilder;
-        log.debug("Revoking direct routing entry for double-tagged host route {} at {}:{}",
-                prefix, deviceId, outPort);
-
-        try {
-            fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac, outerVlan, outPort, innerVlan, outerTpid,
-                    true, true);
-        } catch (DeviceConfigNotFoundException e) {
-            log.error(e.getMessage() + " Aborting revokeDoubleTaggedRoute");
-            return;
-        }
-        if (fwdBuilder == null) {
-            log.error("Aborting double-tagged host routing table entry due to error for dev:{} route:{}",
-                    deviceId, prefix);
-            return;
-        }
-
-        int nextId = fwdBuilder.remove().nextId();
-        DefaultObjectiveContext context = new DefaultObjectiveContext(objective -> {
-            log.debug("Direct routing rule for double-tagged host route {} revoked. nextId={}", prefix, nextId);
-
-            // Try to remove next objective as well
-            ImmutablePair<TrafficTreatment, TrafficSelector> treatmentAndMeta;
-            try {
-                treatmentAndMeta = getTreatmentAndMeta(deviceId, hostMac, outerVlan, outPort, innerVlan, outerTpid);
-            } catch (DeviceConfigNotFoundException e) {
-                log.error(e.getMessage() + " Aborting revokeDoubleTaggedRoute");
-                return;
-            }
-
-            if (treatmentAndMeta == null) {
-                // Warning log will come from getTreatmentAndMeta method
-                return;
-            }
-
-            DefaultGroupHandler groupHandler = srManager.getGroupHandler(deviceId);
-            if (groupHandler == null) {
-                log.warn("Failed to revoke direct routing rule for double-tagged host route {}: " +
-                        "group handler not found for {}", prefix, deviceId);
-                return;
-            }
-            groupHandler.removeGroupFromPort(outPort, treatmentAndMeta.getLeft(), treatmentAndMeta.getRight());
-
-        }, (objective, error) ->
-                log.warn("Failed to revoke direct routing rule for double-tagged host route {}: {}", prefix, error)
-        );
-        srManager.flowObjectiveService.forward(deviceId, fwdBuilder.remove(context));
-    }
-
-    /**
-     * Checks whether the specified port has IP configuration or not.
-     *
-     * @param cp ConnectPoint to check the existance of IP configuration
-     * @return true if the port has IP configuration; false otherwise.
-     */
-    private boolean hasIPConfiguration(ConnectPoint cp) {
-        Set<Interface> interfaces = srManager.interfaceService.getInterfacesByPort(cp);
-        return interfaces.stream().anyMatch(intf -> intf.ipAddressesList().size() > 0);
-    }
-
-    /**
-     * Updates filtering rules for unconfigured ports on all devices for which
-     * this controller instance is master.
-     *
-     * @param pushVlan true if the filtering rule requires a push vlan action
-     * @param oldVlanId the vlanId to be removed
-     * @param newVlanId the vlanId to be added
-     */
-    void updateSpecialVlanFilteringRules(boolean pushVlan, VlanId oldVlanId,
-                                         VlanId newVlanId) {
-        for (Device dev : srManager.deviceService.getAvailableDevices()) {
-            if (srManager.mastershipService.isLocalMaster(dev.id())) {
-                for (Port p : srManager.deviceService.getPorts(dev.id())) {
-                    if (!hasIPConfiguration(new ConnectPoint(dev.id(), p.number()))
-                            && p.isEnabled()) {
-                        updateSinglePortFilters(dev.id(), p.number(), pushVlan,
-                                                oldVlanId, false);
-                        updateSinglePortFilters(dev.id(), p.number(), pushVlan,
-                                                newVlanId, true);
-                    }
-                }
-            }
-        }
-    }
-
-    private boolean isIpv6Configured(DeviceId deviceId) {
-        boolean isIpv6Configured;
-        try {
-            isIpv6Configured = (config.getRouterIpv6(deviceId) != null);
-        } catch (DeviceConfigNotFoundException e) {
-            isIpv6Configured = false;
-        }
-        return isIpv6Configured;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SRLinkWeigher.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SRLinkWeigher.java
deleted file mode 100644
index 01e07a7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SRLinkWeigher.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2018-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 org.onlab.graph.DefaultEdgeWeigher;
-import org.onlab.graph.ScalarWeight;
-import org.onlab.graph.Weight;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.topology.LinkWeigher;
-import org.onosproject.net.topology.TopologyEdge;
-import org.onosproject.net.topology.TopologyVertex;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-
-import java.util.Set;
-
-/**
- * Link weigher for multicast related path computations.
- */
-public final class SRLinkWeigher
-        extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
-        implements LinkWeigher {
-
-    private final SegmentRoutingManager srManager;
-    private final DeviceId srcPath;
-    private final Set<Link> linksToEnforce;
-
-    // Weight for the link to avoids. The high level idea is to build
-    // a constrained shortest path computation. 100 should provide a good
-    // threshold
-    public static final ScalarWeight LINK_TO_AVOID_WEIGHT = new ScalarWeight(HOP_WEIGHT_VALUE + 100);
-
-    /**
-     * Creates a SRLinkWeigher object.
-     *
-     * @param srManager SegmentRoutingManager object
-     * @param srcPath the source of the paths
-     * @param linksToEnforce links to be enforced by the path computation
-     */
-    public SRLinkWeigher(SegmentRoutingManager srManager, DeviceId srcPath,
-                         Set<Link> linksToEnforce) {
-        this.srManager = srManager;
-        this.srcPath = srcPath;
-        this.linksToEnforce = linksToEnforce;
-    }
-
-    @Override
-    public Weight weight(TopologyEdge edge) {
-        // 1) We need to avoid some particular paths like leaf-spine-leaf-*
-        // 2) Properly handle the pair links
-
-        // If the link is a pair link just return infinite value
-        if (isPairLink(edge.link())) {
-            return ScalarWeight.NON_VIABLE_WEIGHT;
-        }
-
-        // To avoid that the paths go through other leaves we need to influence
-        // the path computation to return infinite value for all other links having
-        // as a src a leaf different from the source we are passing to the weigher
-        DeviceId srcDeviceLink = edge.link().src().deviceId();
-        // Identify the link as leaf-spine link
-        boolean isLeafSpine;
-        try {
-            isLeafSpine = srManager.deviceConfiguration().isEdgeDevice(srcDeviceLink);
-        } catch (DeviceConfigNotFoundException e) {
-            isLeafSpine = false;
-        }
-        // If it is not the source just return infinite value
-        if (isLeafSpine && !srcDeviceLink.equals(srcPath)) {
-            return ScalarWeight.NON_VIABLE_WEIGHT;
-        }
-
-        // If the links are not in the list of the links to be enforce
-        if (!linksToEnforce.isEmpty() && !linksToEnforce.contains(edge.link())) {
-            // 100 should be a good confidence threshold
-            return LINK_TO_AVOID_WEIGHT;
-        }
-
-        // All other cases we return
-        return new ScalarWeight(HOP_WEIGHT_VALUE);
-    }
-
-    // Utility method to verify is a link is a pair-link
-    private boolean isPairLink(Link link) {
-        // Take src id, src port, dst id and dst port
-        final DeviceId srcId = link.src().deviceId();
-        final PortNumber srcPort = link.src().port();
-        final DeviceId dstId = link.dst().deviceId();
-        final PortNumber dstPort = link.dst().port();
-        // init as true
-        boolean isPairLink = true;
-        try {
-            // If one of this condition is not true; it is not a pair link
-            if (!(srManager.deviceConfiguration().isEdgeDevice(srcId) &&
-                    srManager.deviceConfiguration().isEdgeDevice(dstId) &&
-                    srManager.deviceConfiguration().getPairDeviceId(srcId).equals(dstId) &&
-                    srManager.deviceConfiguration().getPairLocalPort(srcId).equals(srcPort) &&
-                    srManager.deviceConfiguration().getPairLocalPort(dstId).equals(dstPort))) {
-                isPairLink = false;
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            // Configuration not provided
-            isPairLink = false;
-        }
-        return isPairLink;
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
deleted file mode 100644
index 5f11501..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ /dev/null
@@ -1,2397 +0,0 @@
-/*
- * 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.HashMultimap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onlab.util.Tools;
-import org.onosproject.cfg.ComponentConfigService;
-import org.onosproject.cluster.ClusterEvent;
-import org.onosproject.cluster.ClusterEventListener;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.LeadershipService;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.event.Event;
-import org.onosproject.mastership.MastershipEvent;
-import org.onosproject.mastership.MastershipListener;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.mcast.api.McastEvent;
-import org.onosproject.mcast.api.McastListener;
-import org.onosproject.mcast.api.MulticastRouteService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.ConfigException;
-import org.onosproject.net.config.ConfigFactory;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.config.basics.McastConfig;
-import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.net.device.DeviceAdminService;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostProbingService;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intent.WorkPartitionService;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.net.link.LinkEvent;
-import org.onosproject.net.link.LinkListener;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.net.neighbour.NeighbourResolutionService;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.topology.TopologyEvent;
-import org.onosproject.net.topology.TopologyListener;
-import org.onosproject.net.topology.TopologyService;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteEvent;
-import org.onosproject.routeservice.RouteListener;
-import org.onosproject.routeservice.RouteService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
-import org.onosproject.segmentrouting.mcast.McastFilteringObjStoreKey;
-import org.onosproject.segmentrouting.mcast.McastHandler;
-import org.onosproject.segmentrouting.mcast.McastRole;
-import org.onosproject.segmentrouting.mcast.McastRoleStoreKey;
-import org.onosproject.segmentrouting.mcast.McastStoreKey;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.onosproject.store.service.EventuallyConsistentMapBuilder;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.WallClockTimestamp;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Modified;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.osgi.service.component.annotations.ReferencePolicy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkState;
-import static org.onlab.packet.Ethernet.TYPE_ARP;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_REGISTERED;
-import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UNREGISTERED;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.ACTIVE_PROBING_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.DEFAULT_INTERNAL_VLAN_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_ACTIVE_PROBING;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_DEFAULT_INTERNAL_VLAN;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_PW_TRANSPORT_VLAN;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_RESPOND_TO_UNKNOWN_HOSTS;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_ROUTE_DOUBLE_TAGGED_HOSTS;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_ROUTE_SIMPLIFICATION;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_SINGLE_HOMED_DOWN;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_SYMMETRIC_PROBING;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PW_TRANSPORT_VLAN_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.RESPOND_TO_UNKNOWN_HOSTS_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.ROUTE_SIMPLIFICATION_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.SINGLE_HOMED_DOWN_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.SYMMETRIC_PROBING_DEFAULT;
-
-/**
- * Segment routing manager.
- */
-@Component(
-    immediate = true,
-    service = SegmentRoutingService.class,
-    property = {
-        PROP_ACTIVE_PROBING + ":Boolean=" + ACTIVE_PROBING_DEFAULT,
-        PROP_SINGLE_HOMED_DOWN + ":Boolean=" + SINGLE_HOMED_DOWN_DEFAULT,
-        PROP_RESPOND_TO_UNKNOWN_HOSTS + ":Boolean=" + RESPOND_TO_UNKNOWN_HOSTS_DEFAULT,
-        PROP_ROUTE_DOUBLE_TAGGED_HOSTS + ":Boolean=" + ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT,
-        PROP_DEFAULT_INTERNAL_VLAN + ":Integer=" + DEFAULT_INTERNAL_VLAN_DEFAULT,
-        PROP_PW_TRANSPORT_VLAN + ":Integer=" + PW_TRANSPORT_VLAN_DEFAULT,
-        PROP_SYMMETRIC_PROBING + ":Boolean=" + SYMMETRIC_PROBING_DEFAULT,
-        PROP_ROUTE_SIMPLIFICATION + ":Boolean=" + ROUTE_SIMPLIFICATION_DEFAULT
-    }
-)
-public class SegmentRoutingManager implements SegmentRoutingService {
-
-    private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
-    private static final String NOT_MASTER = "Current instance is not the master of {}. Ignore.";
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private ComponentConfigService compCfgService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public NeighbourResolutionService neighbourResolutionService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public CoreService coreService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    PacketService packetService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    HostService hostService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    HostProbingService probingService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public DeviceService deviceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    DeviceAdminService deviceAdminService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public FlowObjectiveService flowObjectiveService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public LinkService linkService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public MastershipService mastershipService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public StorageService storageService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public MulticastRouteService multicastRouteService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public TopologyService topologyService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public RouteService routeService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public NetworkConfigRegistry cfgService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public InterfaceService interfaceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public ClusterService clusterService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public WorkPartitionService workPartitionService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public LeadershipService leadershipService;
-
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
-            policy = ReferencePolicy.DYNAMIC)
-    public volatile XconnectService xconnectService;
-
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
-            policy = ReferencePolicy.DYNAMIC)
-    volatile PhasedRecoveryService phasedRecoveryService;
-
-    /** Enable active probing to discover dual-homed hosts. */
-    boolean activeProbing = ACTIVE_PROBING_DEFAULT;
-
-    /** Enable only send probe on the same port number of the pair device. */
-    boolean symmetricProbing = SYMMETRIC_PROBING_DEFAULT;
-
-    /** Enable administratively taking down single-homed hosts. */
-    boolean singleHomedDown = SINGLE_HOMED_DOWN_DEFAULT;
-
-    /** Enable this to respond to ARP/NDP requests from unknown hosts. */
-    boolean respondToUnknownHosts = RESPOND_TO_UNKNOWN_HOSTS_DEFAULT;
-
-    /** Program flows and groups to pop and route double tagged hosts. */
-    boolean routeDoubleTaggedHosts = ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT;
-
-    /** internal vlan assigned by default to unconfigured ports. */
-    private int defaultInternalVlan = DEFAULT_INTERNAL_VLAN_DEFAULT;
-
-    /** vlan used for transport of pseudowires between switches. */
-    private int pwTransportVlan = PW_TRANSPORT_VLAN_DEFAULT;
-
-    /** Enabling route simplification. */
-    boolean  routeSimplification = ROUTE_SIMPLIFICATION_DEFAULT;
-
-    ArpHandler arpHandler = null;
-    IcmpHandler icmpHandler = null;
-    IpHandler ipHandler = null;
-    RoutingRulePopulator routingRulePopulator = null;
-    ApplicationId appId;
-    DeviceConfiguration deviceConfiguration = null;
-
-    DefaultRoutingHandler defaultRoutingHandler = null;
-    private TunnelHandler tunnelHandler = null;
-    private PolicyHandler policyHandler = null;
-    private InternalPacketProcessor processor = null;
-    private InternalLinkListener linkListener = null;
-    private InternalDeviceListener deviceListener = null;
-    private AppConfigHandler appCfgHandler = null;
-    McastHandler mcastHandler = null;
-    HostHandler hostHandler = null;
-    private RouteHandler routeHandler = null;
-    LinkHandler linkHandler = null;
-    private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
-    private DefaultL2TunnelHandler l2TunnelHandler = null;
-    private TopologyHandler topologyHandler = null;
-    private final InternalHostListener hostListener = new InternalHostListener();
-    private final InternalConfigListener cfgListener = new InternalConfigListener(this);
-    private final InternalMcastListener mcastListener = new InternalMcastListener();
-    private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
-    private final InternalTopologyListener topologyListener = new InternalTopologyListener();
-    private final InternalMastershipListener mastershipListener = new InternalMastershipListener();
-    final InternalClusterListener clusterListener = new InternalClusterListener();
-    //Completable future for network configuration process to buffer config events handling during activation
-    private CompletableFuture<Boolean> networkConfigCompletion = null;
-    private final Object networkConfigCompletionLock = new Object();
-    private List<Event> queuedEvents = new CopyOnWriteArrayList<>();
-
-    // Handles device, link, topology and network config events
-    private ScheduledExecutorService mainEventExecutor;
-
-    // Handles host, route and mcast events respectively
-    private ScheduledExecutorService hostEventExecutor;
-    private ScheduledExecutorService routeEventExecutor;
-    private ScheduledExecutorService mcastEventExecutor;
-    private ExecutorService packetExecutor;
-    ExecutorService neighborExecutor;
-
-    Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<>();
-    /**
-     * Per device next objective ID store with (device id + destination set) as key.
-     * Used to keep track on MPLS group information.
-     */
-    private EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
-            dsNextObjStore = null;
-    /**
-     * Per device next objective ID store with (device id + vlanid) as key.
-     * Used to keep track on L2 flood group information.
-     */
-    private EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
-            vlanNextObjStore = null;
-    /**
-     * Per device next objective ID store with (device id + port + treatment + meta) as key.
-     * Used to keep track on L2 interface group and L3 unicast group information for direct hosts.
-     */
-    private EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
-            portNextObjStore = null;
-
-    /**
-     * Per device next objective ID store with (device id + MAC address + vlan) as key.
-     * Used to keep track of L3 unicast group for indirect hosts.
-     */
-    private EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer>
-            macVlanNextObjStore = null;
-
-    private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
-    private EventuallyConsistentMap<String, Policy> policyStore = null;
-
-    private AtomicBoolean programmingScheduled = new AtomicBoolean();
-
-    private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
-            new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
-                    SubjectFactories.DEVICE_SUBJECT_FACTORY,
-                    SegmentRoutingDeviceConfig.class, "segmentrouting") {
-                @Override
-                public SegmentRoutingDeviceConfig createConfig() {
-                    return new SegmentRoutingDeviceConfig();
-                }
-            };
-
-    private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
-            new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
-                    SubjectFactories.APP_SUBJECT_FACTORY,
-                    SegmentRoutingAppConfig.class, "segmentrouting") {
-                @Override
-                public SegmentRoutingAppConfig createConfig() {
-                    return new SegmentRoutingAppConfig();
-                }
-            };
-
-    private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
-            new ConfigFactory<ApplicationId, McastConfig>(
-                    SubjectFactories.APP_SUBJECT_FACTORY,
-                    McastConfig.class, "multicast") {
-                @Override
-                public McastConfig createConfig() {
-                    return new McastConfig();
-                }
-            };
-
-    /**
-     * Segment Routing App ID.
-     */
-    public static final String APP_NAME = "org.onosproject.segmentrouting";
-
-    /**
-     * Minumum and maximum value of dummy VLAN ID to be allocated.
-     */
-    public static final int MIN_DUMMY_VLAN_ID = 2;
-    public static final int MAX_DUMMY_VLAN_ID = 4093;
-
-    private static final int DEFAULT_POOL_SIZE = 32;
-
-    Instant lastEdgePortEvent = Instant.EPOCH;
-
-    @Activate
-    protected void activate(ComponentContext context) {
-        appId = coreService.registerApplication(APP_NAME);
-
-        mainEventExecutor = Executors.newSingleThreadScheduledExecutor(
-                groupedThreads("onos/sr", "event-main-%d", log));
-        hostEventExecutor = Executors.newSingleThreadScheduledExecutor(
-                groupedThreads("onos/sr", "event-host-%d", log));
-        routeEventExecutor = Executors.newSingleThreadScheduledExecutor(
-                groupedThreads("onos/sr", "event-route-%d", log));
-        mcastEventExecutor = Executors.newSingleThreadScheduledExecutor(
-                groupedThreads("onos/sr", "event-mcast-%d", log));
-        packetExecutor = Executors.newSingleThreadExecutor(groupedThreads("onos/sr", "packet-%d", log));
-        neighborExecutor = Executors.newFixedThreadPool(DEFAULT_POOL_SIZE,
-                groupedThreads("onos/sr", "neighbor-%d", log));
-
-        log.debug("Creating EC map nsnextobjectivestore");
-        EventuallyConsistentMapBuilder<DestinationSetNextObjectiveStoreKey, NextNeighbors>
-                nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
-        dsNextObjStore = nsNextObjMapBuilder
-                .withName("nsnextobjectivestore")
-                .withSerializer(createSerializer())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-        log.trace("Current size {}", dsNextObjStore.size());
-
-        log.debug("Creating EC map vlannextobjectivestore");
-        EventuallyConsistentMapBuilder<VlanNextObjectiveStoreKey, Integer>
-                vlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
-        vlanNextObjStore = vlanNextObjMapBuilder
-                .withName("vlannextobjectivestore")
-                .withSerializer(createSerializer())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-
-        log.debug("Creating EC map macvlannextobjectivestore");
-        EventuallyConsistentMapBuilder<MacVlanNextObjectiveStoreKey, Integer>
-                macVlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
-        macVlanNextObjStore = macVlanNextObjMapBuilder
-                .withName("macvlannextobjectivestore")
-                .withSerializer(createSerializer())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-
-        log.debug("Creating EC map subnetnextobjectivestore");
-        EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
-                portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
-        portNextObjStore = portNextObjMapBuilder
-                .withName("portnextobjectivestore")
-                .withSerializer(createSerializer())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-
-        EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
-                storageService.eventuallyConsistentMapBuilder();
-        tunnelStore = tunnelMapBuilder
-                .withName("tunnelstore")
-                .withSerializer(createSerializer())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-
-        EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
-                storageService.eventuallyConsistentMapBuilder();
-        policyStore = policyMapBuilder
-                .withName("policystore")
-                .withSerializer(createSerializer())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-
-        processor = new InternalPacketProcessor();
-        linkListener = new InternalLinkListener();
-        deviceListener = new InternalDeviceListener();
-        appCfgHandler = new AppConfigHandler(this);
-        mcastHandler = new McastHandler(this);
-        hostHandler = new HostHandler(this);
-        linkHandler = new LinkHandler(this);
-        routeHandler = new RouteHandler(this);
-        neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
-        l2TunnelHandler = new DefaultL2TunnelHandler(this);
-        topologyHandler = new TopologyHandler(this);
-
-        compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
-                                      "requestInterceptsEnabled", "false", false);
-        compCfgService.preSetProperty("org.onosproject.net.neighbour.impl.NeighbourResolutionManager",
-                                      "requestInterceptsEnabled", "false", false);
-        compCfgService.preSetProperty("org.onosproject.dhcprelay.DhcpRelayManager",
-                                      "arpEnabled", "false", false);
-        compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
-                                      "greedyLearningIpv6", "true", false);
-        compCfgService.preSetProperty("org.onosproject.routing.cpr.ControlPlaneRedirectManager",
-                                      "forceUnprovision", "true", false);
-        compCfgService.preSetProperty("org.onosproject.routeservice.store.RouteStoreImpl",
-                                      "distributed", "true", false);
-        compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
-                                      "multihomingEnabled", "true", false);
-        compCfgService.preSetProperty("org.onosproject.provider.lldp.impl.LldpLinkProvider",
-                                      "staleLinkAge", "15000", false);
-        compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
-                                      "allowDuplicateIps", "false", false);
-        // For P4 switches
-        compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
-                                      "fallbackFlowPollFrequency", "4", false);
-        compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
-                                      "fallbackGroupPollFrequency", "3", false);
-        compCfgService.registerProperties(getClass());
-        modified(context);
-
-        cfgService.addListener(cfgListener);
-        cfgService.registerConfigFactory(deviceConfigFactory);
-        cfgService.registerConfigFactory(appConfigFactory);
-        cfgService.registerConfigFactory(mcastConfigFactory);
-        log.info("Configuring network before adding listeners");
-
-        cfgListener.configureNetwork();
-
-        hostService.addListener(hostListener);
-        packetService.addProcessor(processor, PacketProcessor.director(2));
-        linkService.addListener(linkListener);
-        deviceService.addListener(deviceListener);
-        multicastRouteService.addListener(mcastListener);
-        routeService.addListener(routeListener);
-        topologyService.addListener(topologyListener);
-        mastershipService.addListener(mastershipListener);
-        clusterService.addListener(clusterListener);
-
-        linkHandler.init();
-        l2TunnelHandler.init();
-
-        synchronized (networkConfigCompletionLock) {
-            networkConfigCompletion.whenComplete((value, ex) -> {
-                //setting to null for easier fall through
-                networkConfigCompletion = null;
-                //process all queued events
-                queuedEvents.forEach(event -> {
-                    mainEventExecutor.execute(new InternalEventHandler(event));
-                });
-            });
-        }
-
-        log.info("Started");
-    }
-
-    KryoNamespace.Builder createSerializer() {
-        return new KryoNamespace.Builder()
-                .register(KryoNamespaces.API)
-                .register(DestinationSetNextObjectiveStoreKey.class,
-                          VlanNextObjectiveStoreKey.class,
-                          DestinationSet.class,
-                          DestinationSet.DestinationSetType.class,
-                          NextNeighbors.class,
-                          Tunnel.class,
-                          DefaultTunnel.class,
-                          Policy.class,
-                          TunnelPolicy.class,
-                          Policy.Type.class,
-                          PortNextObjectiveStoreKey.class,
-                          XConnectStoreKey.class,
-                          L2Tunnel.class,
-                          L2TunnelPolicy.class,
-                          DefaultL2Tunnel.class,
-                          DefaultL2TunnelPolicy.class,
-                          MacVlanNextObjectiveStoreKey.class
-                );
-    }
-
-    @Deactivate
-    protected void deactivate() {
-        mainEventExecutor.shutdown();
-        hostEventExecutor.shutdown();
-        routeEventExecutor.shutdown();
-        mcastEventExecutor.shutdown();
-        packetExecutor.shutdown();
-        neighborExecutor.shutdown();
-
-        mainEventExecutor = null;
-        hostEventExecutor = null;
-        routeEventExecutor = null;
-        mcastEventExecutor = null;
-        packetExecutor = null;
-        neighborExecutor = null;
-
-        cfgService.removeListener(cfgListener);
-        cfgService.unregisterConfigFactory(deviceConfigFactory);
-        cfgService.unregisterConfigFactory(appConfigFactory);
-        cfgService.unregisterConfigFactory(mcastConfigFactory);
-        compCfgService.unregisterProperties(getClass(), false);
-
-        hostService.removeListener(hostListener);
-        packetService.removeProcessor(processor);
-        linkService.removeListener(linkListener);
-        deviceService.removeListener(deviceListener);
-        multicastRouteService.removeListener(mcastListener);
-        routeService.removeListener(routeListener);
-        topologyService.removeListener(topologyListener);
-        mastershipService.removeListener(mastershipListener);
-        clusterService.removeListener(clusterListener);
-
-        neighbourResolutionService.unregisterNeighbourHandlers(appId);
-
-        processor = null;
-        linkListener = null;
-        deviceListener = null;
-        groupHandlerMap.forEach((k, v) -> v.shutdown());
-        groupHandlerMap.clear();
-        defaultRoutingHandler.shutdown();
-
-        dsNextObjStore.destroy();
-        vlanNextObjStore.destroy();
-        macVlanNextObjStore.destroy();
-        portNextObjStore.destroy();
-        tunnelStore.destroy();
-        policyStore.destroy();
-
-        mcastHandler.terminate();
-        hostHandler.terminate();
-        log.info("Stopped");
-    }
-
-    @Modified
-    private void modified(ComponentContext context) {
-        Dictionary<?, ?> properties = context.getProperties();
-        if (properties == null) {
-            return;
-        }
-
-        String strActiveProbing = Tools.get(properties, PROP_ACTIVE_PROBING);
-        boolean expectActiveProbing = Boolean.parseBoolean(strActiveProbing);
-        if (expectActiveProbing != activeProbing) {
-            activeProbing = expectActiveProbing;
-            log.info("{} active probing", activeProbing ? "Enabling" : "Disabling");
-        }
-
-
-        String strSymmetricProbing = Tools.get(properties, PROP_SYMMETRIC_PROBING);
-        boolean expectSymmetricProbing = Boolean.parseBoolean(strSymmetricProbing);
-        if (expectSymmetricProbing != symmetricProbing) {
-            symmetricProbing = expectSymmetricProbing;
-            log.info("{} symmetric probing", symmetricProbing ? "Enabling" : "Disabling");
-        }
-
-        String strSingleHomedDown = Tools.get(properties, PROP_SINGLE_HOMED_DOWN);
-        boolean expectSingleHomedDown = Boolean.parseBoolean(strSingleHomedDown);
-        if (expectSingleHomedDown != singleHomedDown) {
-            singleHomedDown = expectSingleHomedDown;
-            log.info("{} downing of single homed hosts for lost uplinks",
-                     singleHomedDown ? "Enabling" : "Disabling");
-            if (singleHomedDown && linkHandler != null) {
-                hostService.getHosts().forEach(host -> host.locations()
-                        .forEach(loc -> {
-                            if (interfaceService.isConfigured(loc)) {
-                                linkHandler.checkUplinksForHost(loc);
-                            }
-                        }));
-            } else {
-                log.warn("Disabling singleHomedDown does not re-enable already "
-                        + "downed ports for single-homed hosts");
-            }
-        }
-
-        String strRespondToUnknownHosts = Tools.get(properties, PROP_RESPOND_TO_UNKNOWN_HOSTS);
-        boolean expectRespondToUnknownHosts = Boolean.parseBoolean(strRespondToUnknownHosts);
-        if (expectRespondToUnknownHosts != respondToUnknownHosts) {
-            respondToUnknownHosts = expectRespondToUnknownHosts;
-            log.info("{} responding to ARPs/NDPs from unknown hosts", respondToUnknownHosts ? "Enabling" : "Disabling");
-        }
-
-        String strRouteDoubleTaggedHosts = Tools.get(properties, PROP_ROUTE_DOUBLE_TAGGED_HOSTS);
-        boolean expectRouteDoubleTaggedHosts = Boolean.parseBoolean(strRouteDoubleTaggedHosts);
-        if (expectRouteDoubleTaggedHosts != routeDoubleTaggedHosts) {
-            routeDoubleTaggedHosts = expectRouteDoubleTaggedHosts;
-            log.info("{} routing for double tagged hosts", routeDoubleTaggedHosts ? "Enabling" : "Disabling");
-
-            if (routeDoubleTaggedHosts) {
-                hostHandler.populateAllDoubleTaggedHost();
-            } else {
-                hostHandler.revokeAllDoubleTaggedHost();
-            }
-        }
-
-        String strDefaultInternalVlan = Tools.get(properties, PROP_DEFAULT_INTERNAL_VLAN);
-        int defIntVlan = Integer.parseInt(strDefaultInternalVlan);
-        if (defIntVlan != defaultInternalVlan) {
-            if (canUseVlanId(defIntVlan)) {
-                log.warn("Default internal vlan value changed from {} to {}.. "
-                        + "re-programming filtering rules, but NOT any groups already "
-                        + "created with the former value", defaultInternalVlan, defIntVlan);
-                VlanId oldDefIntVlan = VlanId.vlanId((short) defaultInternalVlan);
-                defaultInternalVlan = defIntVlan;
-                routingRulePopulator
-                .updateSpecialVlanFilteringRules(true, oldDefIntVlan,
-                                                 VlanId.vlanId((short) defIntVlan));
-            } else {
-                log.warn("Cannot change default internal vlan to unusable "
-                        + "value {}", defIntVlan);
-            }
-        }
-
-        String strPwTxpVlan = Tools.get(properties, PROP_PW_TRANSPORT_VLAN);
-        int pwTxpVlan = Integer.parseInt(strPwTxpVlan);
-        if (pwTxpVlan != pwTransportVlan) {
-            if (canUseVlanId(pwTxpVlan)) {
-                log.warn("Pseudowire transport vlan value changed from {} to {}.. "
-                        + "re-programming filtering rules, but NOT any groups already "
-                        + "created with the former value", pwTransportVlan,
-                        pwTxpVlan);
-                VlanId oldPwTxpVlan = VlanId.vlanId((short) pwTransportVlan);
-                pwTransportVlan = pwTxpVlan;
-                routingRulePopulator
-                .updateSpecialVlanFilteringRules(false, oldPwTxpVlan,
-                                                 VlanId.vlanId((short) pwTxpVlan));
-            } else {
-                log.warn("Cannot change pseudowire transport vlan to unusable "
-                        + "value {}", pwTxpVlan);
-            }
-        }
-
-        String strRouteSimplification = Tools.get(properties, PROP_ROUTE_SIMPLIFICATION);
-        boolean expectRouteSimplification = Boolean.parseBoolean(strRouteSimplification);
-        if (expectRouteSimplification != routeSimplification) {
-            routeSimplification = expectRouteSimplification;
-            log.info("{} route simplification", routeSimplification ? "Enabling" : "Disabling");
-        }
-
-    }
-
-    /**
-     * Returns true if given vlan id is not being used in the system currently,
-     * either as one of the default system wide vlans or as one of the
-     * configured interface vlans.
-     *
-     * @param vlanId given vlan id
-     * @return true if vlan is not currently in use
-     */
-    public boolean canUseVlanId(int vlanId) {
-        if (vlanId >= 4095 || vlanId <= 1) {
-            log.error("Vlan id {} value is not in valid range 2 <--> 4094",
-                      vlanId);
-            return false;
-        }
-
-       VlanId vid = VlanId.vlanId((short) vlanId);
-        if (getDefaultInternalVlan().equals(vid) || getPwTransportVlan().equals(vid)) {
-            log.warn("Vlan id {} value is already in use system-wide. "
-                    + "DefaultInternalVlan:{} PwTransportVlan:{} ", vlanId,
-                     getDefaultInternalVlan(), getPwTransportVlan());
-            return false;
-        }
-
-        if (interfaceService.inUse(vid)) {
-            log.warn("Vlan id {} value is already in use on a configured "
-                    + "interface in the system", vlanId);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Returns the VlanId assigned internally by default to unconfigured ports.
-     *
-     * @return the default internal vlan id
-     */
-    public VlanId getDefaultInternalVlan() {
-        return VlanId.vlanId((short) defaultInternalVlan);
-    }
-
-    /**
-     * Returns the Vlan id used to transport pseudowire traffic across the
-     * network.
-     *
-     * @return the pseudowire transport vlan id
-     */
-    public VlanId getPwTransportVlan() {
-        return VlanId.vlanId((short) pwTransportVlan);
-    }
-
-    @Override
-    public List<Tunnel> getTunnels() {
-        return tunnelHandler.getTunnels();
-    }
-
-    @Override
-    public TunnelHandler.Result createTunnel(Tunnel tunnel) {
-        return tunnelHandler.createTunnel(tunnel);
-    }
-
-    @Override
-    public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
-        for (Policy policy: policyHandler.getPolicies()) {
-            if (policy.type() == Policy.Type.TUNNEL_FLOW) {
-                TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
-                if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
-                    log.warn("Cannot remove the tunnel used by a policy");
-                    return TunnelHandler.Result.TUNNEL_IN_USE;
-                }
-            }
-        }
-        return tunnelHandler.removeTunnel(tunnel);
-    }
-
-    @Override
-    public PolicyHandler.Result removePolicy(Policy policy) {
-        return policyHandler.removePolicy(policy);
-    }
-
-    @Override
-    public PolicyHandler.Result createPolicy(Policy policy) {
-        return policyHandler.createPolicy(policy);
-    }
-
-    @Override
-    public List<Policy> getPolicies() {
-        return policyHandler.getPolicies();
-    }
-
-    @Override
-    public Set<L2TunnelDescription> getL2TunnelDescriptions(boolean pending) {
-        return l2TunnelHandler.getL2Descriptions(pending);
-    }
-
-    @Override
-    public List<L2Tunnel> getL2Tunnels() {
-        return l2TunnelHandler.getL2Tunnels();
-    }
-
-    @Override
-    public List<L2TunnelPolicy> getL2Policies() {
-        return l2TunnelHandler.getL2Policies();
-    }
-
-    @Override
-    @Deprecated
-    public L2TunnelHandler.Result addPseudowiresBulk(List<DefaultL2TunnelDescription> bulkPseudowires) {
-
-        // get both added and pending pseudowires
-        List<L2TunnelDescription> pseudowires = new ArrayList<>();
-        pseudowires.addAll(l2TunnelHandler.getL2Descriptions(false));
-        pseudowires.addAll(l2TunnelHandler.getL2Descriptions(true));
-        pseudowires.addAll(bulkPseudowires);
-
-        Set<L2TunnelDescription> newPseudowires = new HashSet(bulkPseudowires);
-
-        L2TunnelHandler.Result retRes = L2TunnelHandler.Result.SUCCESS;
-        L2TunnelHandler.Result res;
-        for (DefaultL2TunnelDescription pw : bulkPseudowires) {
-            res = addPseudowire(pw);
-            if (res != L2TunnelHandler.Result.SUCCESS) {
-                log.error("Pseudowire with id {} can not be instantiated !", res);
-                retRes = res;
-            }
-        }
-
-        return retRes;
-    }
-
-    @Override
-    public L2TunnelHandler.Result addPseudowire(L2TunnelDescription l2TunnelDescription) {
-        return l2TunnelHandler.deployPseudowire(l2TunnelDescription);
-    }
-
-    @Override
-    public L2TunnelHandler.Result removePseudowire(Integer pwId) {
-        return l2TunnelHandler.tearDownPseudowire(pwId);
-    }
-
-    @Override
-    public void rerouteNetwork() {
-        cfgListener.configureNetwork();
-    }
-
-    @Override
-    public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
-        Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
-        deviceConfiguration.getRouters().forEach(device ->
-            deviceSubnetMap.put(device, deviceConfiguration.getSubnets(device)));
-        return deviceSubnetMap;
-    }
-
-
-    @Override
-    public ImmutableMap<DeviceId, EcmpShortestPathGraph> getCurrentEcmpSpg() {
-        if (defaultRoutingHandler != null) {
-            return defaultRoutingHandler.getCurrentEmcpSpgMap();
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    public ImmutableMap<DestinationSetNextObjectiveStoreKey, NextNeighbors> getDstNextObjStore() {
-        if (dsNextObjStore != null) {
-            return ImmutableMap.copyOf(dsNextObjStore.entrySet());
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public ImmutableMap<VlanNextObjectiveStoreKey, Integer> getVlanNextObjStore() {
-        if (vlanNextObjStore != null) {
-            return ImmutableMap.copyOf(vlanNextObjStore.entrySet());
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public ImmutableMap<MacVlanNextObjectiveStoreKey, Integer> getMacVlanNextObjStore() {
-        if (macVlanNextObjStore != null) {
-            return ImmutableMap.copyOf(macVlanNextObjStore.entrySet());
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public ImmutableMap<PortNextObjectiveStoreKey, Integer> getPortNextObjStore() {
-        if (portNextObjStore != null) {
-            return ImmutableMap.copyOf(portNextObjStore.entrySet());
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public ImmutableMap<String, NextObjective> getPwInitNext() {
-        if (l2TunnelHandler != null) {
-            return l2TunnelHandler.getInitNext();
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public ImmutableMap<String, NextObjective> getPwTermNext() {
-        if (l2TunnelHandler != null) {
-            return l2TunnelHandler.getTermNext();
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public void invalidateNextObj(int nextId) {
-        if (dsNextObjStore != null) {
-            dsNextObjStore.entrySet().forEach(e -> {
-                if (e.getValue().nextId() == nextId) {
-                    dsNextObjStore.remove(e.getKey());
-                }
-            });
-        }
-        if (vlanNextObjStore != null) {
-            vlanNextObjStore.entrySet().forEach(e -> {
-                if (e.getValue() == nextId) {
-                    vlanNextObjStore.remove(e.getKey());
-                }
-            });
-        }
-        if (macVlanNextObjStore != null) {
-            macVlanNextObjStore.entrySet().forEach(e -> {
-                if (e.getValue() == nextId) {
-                    macVlanNextObjStore.remove(e.getKey());
-                }
-            });
-        }
-        if (portNextObjStore != null) {
-            portNextObjStore.entrySet().forEach(e -> {
-                if (e.getValue() == nextId) {
-                    portNextObjStore.remove(e.getKey());
-                }
-            });
-        }
-        if (mcastHandler != null) {
-            mcastHandler.removeNextId(nextId);
-        }
-        if (l2TunnelHandler != null) {
-            l2TunnelHandler.removeNextId(nextId);
-        }
-        if (xconnectService != null) {
-            xconnectService.removeNextId(nextId);
-        }
-    }
-
-    @Override
-    public void verifyGroups(DeviceId id) {
-        DefaultGroupHandler gh = groupHandlerMap.get(id);
-        if (gh != null) {
-            gh.triggerBucketCorrector();
-        }
-    }
-
-    @Override
-    public ImmutableMap<Link, Boolean> getSeenLinks() {
-        return linkHandler.getSeenLinks();
-    }
-
-    @Override
-    public ImmutableMap<DeviceId, Set<PortNumber>> getDownedPortState() {
-        return linkHandler.getDownedPorts();
-    }
-
-    @Override
-    public Map<McastStoreKey, Integer> getMcastNextIds(IpAddress mcastIp) {
-        return mcastHandler.getNextIds(mcastIp);
-    }
-
-    @Override
-    public Map<McastRoleStoreKey, McastRole> getMcastRoles(IpAddress mcastIp, ConnectPoint sourcecp) {
-        return mcastHandler.getMcastRoles(mcastIp, sourcecp);
-    }
-
-    @Override
-    public Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
-                                                                    ConnectPoint sourcecp) {
-        return mcastHandler.getMcastTrees(mcastIp, sourcecp);
-    }
-
-    @Override
-    public Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp) {
-        return mcastHandler.getMcastLeaders(mcastIp);
-    }
-
-    @Override
-    public Map<DeviceId, List<McastFilteringObjStoreKey>> getMcastFilters() {
-        return mcastHandler.getMcastFilters();
-    }
-
-    @Override
-    public Map<Set<DeviceId>, NodeId> getShouldProgram() {
-        return defaultRoutingHandler == null ? ImmutableMap.of() :
-                ImmutableMap.copyOf(defaultRoutingHandler.shouldProgram);
-    }
-
-    @Override
-    public Map<DeviceId, Boolean> getShouldProgramCache() {
-        return defaultRoutingHandler == null ? ImmutableMap.of() :
-                ImmutableMap.copyOf(defaultRoutingHandler.shouldProgramCache);
-    }
-
-    @Override
-    public boolean shouldProgram(DeviceId deviceId) {
-        return defaultRoutingHandler.shouldProgram(deviceId);
-    }
-
-    @Override
-    public boolean isRoutingStable() {
-        return defaultRoutingHandler.isRoutingStable();
-    }
-
-    @Override
-    public void initHost(DeviceId deviceId) {
-        hostEventExecutor.execute(() -> hostHandler.init(deviceId));
-    }
-
-    @Override
-    public void initRoute(DeviceId deviceId) {
-        routeEventExecutor.execute(() -> routeHandler.init(deviceId));
-    }
-
-    @Override
-    public ApplicationId appId() {
-        return appId;
-    }
-
-    /**
-     * Returns the device configuration.
-     *
-     * @return device configuration
-     */
-    public DeviceConfiguration deviceConfiguration() {
-        return deviceConfiguration;
-    }
-
-    /**
-     * Per device next objective ID store with (device id + destination set) as key.
-     * Used to keep track on MPLS group information.
-     *
-     * @return next objective ID store
-     */
-    public EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
-                dsNextObjStore() {
-        return dsNextObjStore;
-    }
-
-    /**
-     * Per device next objective ID store with (device id + vlanid) as key.
-     * Used to keep track on L2 flood group information.
-     *
-     * @return vlan next object store
-     */
-    public EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer> vlanNextObjStore() {
-        return vlanNextObjStore;
-    }
-
-    /**
-     * Per device next objective ID store with (device id + MAC address + vlan) as key.
-     * Used to keep track on L3 Unicast group information for indirect hosts.
-     *
-     * @return mac vlan next object store
-     */
-    public EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer> macVlanNextObjStore() {
-        return macVlanNextObjStore;
-    }
-
-    /**
-     * Per device next objective ID store with (device id + port + treatment + meta) as key.
-     * Used to keep track on L2 interface group and L3 unicast group information for direct hosts.
-     *
-     * @return port next object store.
-     */
-    public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer> portNextObjStore() {
-        return portNextObjStore;
-    }
-
-    /**
-     * Returns the MPLS-ECMP configuration which indicates whether ECMP on
-     * labeled packets should be programmed or not.
-     *
-     * @return MPLS-ECMP value
-     */
-    public boolean getMplsEcmp() {
-        SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
-                .getConfig(this.appId, SegmentRoutingAppConfig.class);
-        return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
-    }
-
-    /**
-     * Returns the tunnel object with the tunnel ID.
-     *
-     * @param tunnelId Tunnel ID
-     * @return Tunnel reference
-     */
-    public Tunnel getTunnel(String tunnelId) {
-        return tunnelHandler.getTunnel(tunnelId);
-    }
-
-    @Override
-    public VlanId getInternalVlanId(ConnectPoint connectPoint) {
-        VlanId untaggedVlanId = interfaceService.getUntaggedVlanId(connectPoint);
-        VlanId nativeVlanId = interfaceService.getNativeVlanId(connectPoint);
-        return untaggedVlanId != null ? untaggedVlanId : nativeVlanId;
-    }
-
-    @Override
-    public Optional<DeviceId> getPairDeviceId(DeviceId deviceId) {
-        SegmentRoutingDeviceConfig deviceConfig =
-                cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
-        return Optional.ofNullable(deviceConfig).map(SegmentRoutingDeviceConfig::pairDeviceId);
-    }
-
-    @Override
-    public Optional<PortNumber> getPairLocalPort(DeviceId deviceId) {
-        SegmentRoutingDeviceConfig deviceConfig =
-                cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
-        return Optional.ofNullable(deviceConfig).map(SegmentRoutingDeviceConfig::pairLocalPort);
-    }
-
-    @Override
-    public Set<PortNumber> getInfraPorts(DeviceId deviceId) {
-        return deviceService.getPorts(deviceId).stream()
-                .map(port -> new ConnectPoint(port.element().id(), port.number()))
-                .filter(cp -> interfaceService.getInterfacesByPort(cp).isEmpty())
-                .map(ConnectPoint::port)
-                .collect(Collectors.toSet());
-    }
-
-    @Override
-    public Set<PortNumber> getEdgePorts(DeviceId deviceId) {
-        return deviceService.getPorts(deviceId).stream()
-                .map(port -> new ConnectPoint(port.element().id(), port.number()))
-                .filter(cp -> !interfaceService.getInterfacesByPort(cp).isEmpty() &&
-                        !cp.port().equals(getPairLocalPort(deviceId).orElse(null)))
-                .map(ConnectPoint::port)
-                .collect(Collectors.toSet());
-    }
-
-    /**
-     * Returns locations of given resolved route.
-     *
-     * @param resolvedRoute resolved route
-     * @return locations of nexthop. Might be empty if next hop is not found
-     */
-    public Set<ConnectPoint> nextHopLocations(ResolvedRoute resolvedRoute) {
-        HostId hostId = HostId.hostId(resolvedRoute.nextHopMac(), resolvedRoute.nextHopVlan());
-        return Optional.ofNullable(hostService.getHost(hostId))
-                .map(Host::locations).orElse(Sets.newHashSet())
-                .stream().map(l -> (ConnectPoint) l).collect(Collectors.toSet());
-    }
-
-    /**
-     * Returns vlan port map of given device.
-     *
-     * @param deviceId device id
-     * @return vlan-port multimap
-     */
-    public Multimap<VlanId, PortNumber> getVlanPortMap(DeviceId deviceId) {
-        HashMultimap<VlanId, PortNumber> vlanPortMap = HashMultimap.create();
-
-        interfaceService.getInterfaces().stream()
-                .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
-                .forEach(intf -> {
-                    vlanPortMap.put(intf.vlanUntagged(), intf.connectPoint().port());
-                    intf.vlanTagged().forEach(vlanTagged ->
-                        vlanPortMap.put(vlanTagged, intf.connectPoint().port())
-                    );
-                    vlanPortMap.put(intf.vlanNative(), intf.connectPoint().port());
-                });
-        vlanPortMap.removeAll(VlanId.NONE);
-
-        return vlanPortMap;
-    }
-
-    /**
-     * Returns the next objective ID for the given vlan id. It is expected
-     * that the next-objective has been pre-created from configuration.
-     *
-     * @param deviceId Device ID
-     * @param vlanId VLAN ID
-     * @return next objective ID or -1 if it was not found
-     */
-    int getVlanNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
-        if (groupHandlerMap.get(deviceId) != null) {
-            log.trace("getVlanNextObjectiveId query in device {}", deviceId);
-            return groupHandlerMap.get(deviceId).getVlanNextObjectiveId(vlanId);
-        } else {
-            log.warn("getVlanNextObjectiveId query - groupHandler for "
-                    + "device {} not found", deviceId);
-            return -1;
-        }
-    }
-
-    /**
-     * Returns the next objective ID for the given portNumber, given the treatment.
-     * There could be multiple different treatments to the same outport, which
-     * would result in different objectives. If the next object does not exist,
-     * and should be created, a new one is created and its id is returned.
-     *
-     * @param deviceId Device ID
-     * @param portNum port number on device for which NextObjective is queried
-     * @param treatment the actions to apply on the packets (should include outport)
-     * @param meta metadata passed into the creation of a Next Objective if necessary
-     * @param createIfMissing true if a next object should be created if not found
-     * @return next objective ID or -1 if an error occurred during retrieval or creation
-     */
-    public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
-                                      TrafficTreatment treatment,
-                                      TrafficSelector meta,
-                                      boolean createIfMissing) {
-        DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
-        if (ghdlr != null) {
-            return ghdlr.getPortNextObjectiveId(portNum, treatment, meta, createIfMissing);
-        } else {
-            log.warn("getPortNextObjectiveId query - groupHandler for device {}"
-                    + " not found", deviceId);
-            return -1;
-        }
-    }
-
-    /**
-     * Returns the next Objective ID for the given mac and vlan, given the treatment.
-     * There could be multiple different treatments to the same outport, which
-     * would result in different objectives. If the next object does not exist,
-     * and should be created, a new one is created and its id is returned.
-     *
-     * @param deviceId Device ID
-     * @param macAddr mac of host for which Next ID is required.
-     * @param vlanId vlan of host for which Next ID is required.
-     * @param port port with which to create the Next Obj.
-     * @param createIfMissing true if a next object should be created if not found
-     * @return next objective ID or -1 if an error occurred during retrieval or creation
-     */
-    public int getMacVlanNextObjectiveId(DeviceId deviceId, MacAddress macAddr, VlanId vlanId,
-                                      PortNumber port, boolean createIfMissing) {
-        DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
-        if (ghdlr != null) {
-            return ghdlr.getMacVlanNextObjectiveId(macAddr, vlanId, port, createIfMissing);
-        } else {
-            log.warn("getMacVlanNextObjectiveId query - groupHandler for device {}"
-                    + " not found", deviceId);
-            return -1;
-        }
-    }
-
-    /**
-     * Updates the next objective for the given nextId .
-     *
-     * @param deviceId Device ID
-     * @param hostMac mac of host for which Next obj is to be updated.
-     * @param hostVlanId vlan of host for which Next obj is to be updated.
-     * @param port port with which to update the Next Obj.
-     * @param nextId of Next Obj which needs to be updated.
-     */
-    public void updateMacVlanTreatment(DeviceId deviceId, MacAddress hostMac,
-                             VlanId hostVlanId, PortNumber port, int nextId) {
-        // Check if we are the king of this device
-        // just one instance should perform this update
-        if (!defaultRoutingHandler.shouldProgram(deviceId)) {
-            log.debug("This instance is not handling the routing towards the "
-                              + "device {}", deviceId);
-            return;
-        }
-        // Get the handler and perform the update
-        DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
-        if (ghdlr != null) {
-            ghdlr.updateL3UcastGroupBucket(hostMac, hostVlanId, port, nextId);
-        } else {
-            log.warn("updateL3UcastGroupBucket query - groupHandler for device {}"
-                    + " not found", deviceId);
-        }
-    }
-
-
-    /**
-     * Returns the group handler object for the specified device id.
-     *
-     * @param devId the device identifier
-     * @return the groupHandler object for the device id, or null if not found
-     */
-    DefaultGroupHandler getGroupHandler(DeviceId devId) {
-        return groupHandlerMap.get(devId);
-    }
-
-    /**
-     * Returns the default routing handler object.
-     *
-     * @return the default routing handler object
-     */
-    public DefaultRoutingHandler getRoutingHandler() {
-        return defaultRoutingHandler;
-    }
-
-    private class InternalPacketProcessor implements PacketProcessor {
-        @Override
-        public void process(PacketContext context) {
-            packetExecutor.execute(() -> processPacketInternal(context));
-        }
-
-        private void processPacketInternal(PacketContext context) {
-            if (context.isHandled()) {
-                return;
-            }
-
-            InboundPacket pkt = context.inPacket();
-            Ethernet ethernet = pkt.parsed();
-
-            if (ethernet == null) {
-                return;
-            }
-
-            log.trace("Rcvd pktin from {}: {}", context.inPacket().receivedFrom(),
-                      ethernet);
-            if (ethernet.getEtherType() == TYPE_ARP) {
-                log.warn("Received unexpected ARP packet on {}",
-                         context.inPacket().receivedFrom());
-                log.trace("{}", ethernet);
-                return;
-            } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
-                IPv4 ipv4Packet = (IPv4) ethernet.getPayload();
-                //ipHandler.addToPacketBuffer(ipv4Packet);
-                if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) {
-                    icmpHandler.processIcmp(ethernet, pkt.receivedFrom());
-                } else {
-                    // NOTE: We don't support IP learning at this moment so this
-                    //       is not necessary. Also it causes duplication of DHCP packets.
-                    // ipHandler.processPacketIn(ipv4Packet, pkt.receivedFrom());
-                }
-            } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
-                IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
-                //ipHandler.addToPacketBuffer(ipv6Packet);
-                // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
-                if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
-                    ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
-                    if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST ||
-                            icmp6Packet.getIcmpType() == ICMP6.ECHO_REPLY) {
-                        icmpHandler.processIcmpv6(ethernet, pkt.receivedFrom());
-                    } else {
-                        log.trace("Received ICMPv6 0x{} - not handled",
-                                Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
-                    }
-                } else {
-                   // NOTE: We don't support IP learning at this moment so this
-                   //       is not necessary. Also it causes duplication of DHCPv6 packets.
-                   // ipHandler.processPacketIn(ipv6Packet, pkt.receivedFrom());
-                }
-            }
-        }
-    }
-
-    private class InternalEventHandler implements Runnable {
-        private Event event;
-
-        InternalEventHandler(Event event) {
-            this.event = event;
-        }
-
-        @Override
-        public void run() {
-            try {
-                // TODO We should also change SR routing and PW to listen to TopologyEvents
-                if (event.type() == LinkEvent.Type.LINK_ADDED ||
-                        event.type() == LinkEvent.Type.LINK_UPDATED) {
-                    linkHandler.processLinkAdded((Link) event.subject());
-                } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
-                    linkHandler.processLinkRemoved((Link) event.subject());
-                } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
-                        event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
-                        event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
-                    DeviceId deviceId = ((Device) event.subject()).id();
-                    if (deviceService.isAvailable(deviceId)) {
-                        log.info("** DEVICE UP Processing device event {} "
-                                + "for available device {}",
-                                 event.type(), ((Device) event.subject()).id());
-                        processDeviceAdded((Device) event.subject());
-                    } else {
-                        if (event.type() == DeviceEvent.Type.DEVICE_ADDED) {
-                            // Note: For p4 devices, the device will be added but unavailable at the beginning.
-                            //       The device will later on being marked as available once the pipeline is pushed
-                            //       to the device.
-                            log.info("** DEVICE ADDED but unavailable. Ignore");
-                            return;
-                        }
-                        log.info(" ** DEVICE DOWN Processing device event {}"
-                                + " for unavailable device {}",
-                                 event.type(), ((Device) event.subject()).id());
-                        processDeviceRemoved((Device) event.subject());
-                    }
-                } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
-                    // typically these calls come when device is added first time
-                    // so port filtering rules are handled at the device_added event.
-                    // port added calls represent all ports on the device,
-                    // enabled or not.
-                    log.trace("** PORT ADDED {}/{} -> {}",
-                              ((DeviceEvent) event).subject().id(),
-                              ((DeviceEvent) event).port().number(),
-                              event.type());
-                } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
-                    // these calls happen for every subsequent event
-                    // ports enabled, disabled, switch goes away, comes back
-                    log.info("** PORT UPDATED {}/{} -> {}",
-                             event.subject(),
-                             ((DeviceEvent) event).port(),
-                             event.type());
-                    processPortUpdatedInternal(((Device) event.subject()),
-                                       ((DeviceEvent) event).port());
-                    mcastHandler.processPortUpdate(((Device) event.subject()),
-                                                   ((DeviceEvent) event).port());
-                } else if (event.type() == TopologyEvent.Type.TOPOLOGY_CHANGED) {
-                    // Process topology event, needed for all modules relying on
-                    // topology service for path computation
-                    TopologyEvent topologyEvent = (TopologyEvent) event;
-                    log.info("Processing topology event {}, topology age {}, reasons {}",
-                             event.type(), topologyEvent.subject().time(),
-                             topologyEvent.reasons().size());
-                    topologyHandler.processTopologyChange(topologyEvent.reasons());
-                } else if (event.type() == HostEvent.Type.HOST_ADDED) {
-                    hostHandler.processHostAddedEvent((HostEvent) event);
-                } else if (event.type() == HostEvent.Type.HOST_MOVED) {
-                    hostHandler.processHostMovedEvent((HostEvent) event);
-                    routeHandler.processHostMovedEvent((HostEvent) event);
-                } else if (event.type() == HostEvent.Type.HOST_AUX_MOVED) {
-                    hostHandler.processHostMovedEvent((HostEvent) event);
-                    // TODO RouteHandler also needs to process this event in order to
-                    //      support nexthops that has auxLocations
-                } else if (event.type() == HostEvent.Type.HOST_REMOVED) {
-                    hostHandler.processHostRemovedEvent((HostEvent) event);
-                } else if (event.type() == HostEvent.Type.HOST_UPDATED) {
-                    hostHandler.processHostUpdatedEvent((HostEvent) event);
-                } else if (event.type() == RouteEvent.Type.ROUTE_ADDED) {
-                    routeHandler.processRouteAdded((RouteEvent) event);
-                } else if (event.type() == RouteEvent.Type.ROUTE_UPDATED) {
-                    routeHandler.processRouteUpdated((RouteEvent) event);
-                } else if (event.type() == RouteEvent.Type.ROUTE_REMOVED) {
-                    routeHandler.processRouteRemoved((RouteEvent) event);
-                } else if (event.type() == RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED) {
-                    routeHandler.processAlternativeRoutesChanged((RouteEvent) event);
-                } else if (event.type() == McastEvent.Type.SOURCES_ADDED ||
-                        event.type() == McastEvent.Type.SOURCES_REMOVED ||
-                        event.type() == McastEvent.Type.SINKS_ADDED ||
-                        event.type() == McastEvent.Type.SINKS_REMOVED ||
-                        event.type() == McastEvent.Type.ROUTE_ADDED ||
-                        event.type() == McastEvent.Type.ROUTE_REMOVED) {
-                    mcastHandler.processMcastEvent((McastEvent) event);
-                } else if (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
-                    NetworkConfigEvent netcfgEvent = (NetworkConfigEvent) event;
-                    Class configClass = netcfgEvent.configClass();
-                    if (configClass.equals(SegmentRoutingAppConfig.class)) {
-                        appCfgHandler.processAppConfigAdded(netcfgEvent);
-                        log.info("App config event .. configuring network");
-                        cfgListener.configureNetwork();
-                    } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
-                        log.info("Segment Routing Device Config added for {}", event.subject());
-                        cfgListener.configureNetwork();
-                    } else if (configClass.equals(InterfaceConfig.class)) {
-                        log.info("Interface Config added for {}", event.subject());
-                        cfgListener.configureNetwork();
-                    } else {
-                        log.error("Unhandled config class: {}", configClass);
-                    }
-                } else if (event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) {
-                    NetworkConfigEvent netcfgEvent = (NetworkConfigEvent) event;
-                    Class configClass = netcfgEvent.configClass();
-                    if (configClass.equals(SegmentRoutingAppConfig.class)) {
-                        appCfgHandler.processAppConfigUpdated(netcfgEvent);
-                        log.info("App config event .. configuring network");
-                        cfgListener.configureNetwork();
-                    } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
-                        log.info("Segment Routing Device Config updated for {}", event.subject());
-                        createOrUpdateDeviceConfiguration();
-                    } else if (configClass.equals(InterfaceConfig.class)) {
-                        log.info("Interface Config updated for {}", event.subject());
-                        createOrUpdateDeviceConfiguration();
-                        updateInterface((InterfaceConfig) netcfgEvent.config().get(),
-                                (InterfaceConfig) netcfgEvent.prevConfig().get());
-                    } else {
-                        log.error("Unhandled config class: {}", configClass);
-                    }
-                } else if (event.type() == NetworkConfigEvent.Type.CONFIG_REMOVED) {
-                    NetworkConfigEvent netcfgEvent = (NetworkConfigEvent) event;
-                    Class configClass = netcfgEvent.configClass();
-                    if (configClass.equals(SegmentRoutingAppConfig.class)) {
-                        appCfgHandler.processAppConfigRemoved(netcfgEvent);
-                        log.info("App config event .. configuring network");
-                        cfgListener.configureNetwork();
-                    } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
-                        // TODO Handle sr device config removal
-                        log.info("SegmentRoutingDeviceConfig removal is not handled in current implementation");
-                    } else if (configClass.equals(InterfaceConfig.class)) {
-                        // TODO Handle interface removal
-                        log.info("InterfaceConfig removal is not handled in current implementation");
-                    } else {
-                        log.error("Unhandled config class: {}", configClass);
-                    }
-                } else if (event.type() == MastershipEvent.Type.MASTER_CHANGED) {
-                    MastershipEvent me = (MastershipEvent) event;
-                    DeviceId deviceId = me.subject();
-                    Optional<DeviceId> pairDeviceId = getPairDeviceId(deviceId);
-                    log.info(" ** MASTERSHIP CHANGED Invalidating shouldProgram cache"
-                            + " for {}/pair={} due to change", deviceId, pairDeviceId);
-                    defaultRoutingHandler.invalidateShouldProgramCache(deviceId);
-                    pairDeviceId.ifPresent(defaultRoutingHandler::invalidateShouldProgramCache);
-                    defaultRoutingHandler.checkFullRerouteForMasterChange(deviceId, me);
-                } else {
-                    log.warn("Unhandled event type: {}", event.type());
-                }
-            } catch (Exception e) {
-                log.error("SegmentRouting event handler thread thrown an exception: {}",
-                          e.getMessage(), e);
-            }
-        }
-    }
-
-    void processDeviceAdded(Device device) {
-        log.info("** DEVICE ADDED with ID {}", device.id());
-
-        // NOTE: Punt ARP/NDP even when the device is not configured.
-        //       Host learning without network config is required for CORD config generator.
-        routingRulePopulator.populateIpPunts(device.id());
-        routingRulePopulator.populateArpNdpPunts(device.id());
-
-        if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
-            log.warn("Device configuration unavailable. Device {} will be "
-                    + "processed after configuration.", device.id());
-            return;
-        }
-        processDeviceAddedInternal(device.id());
-    }
-
-    private void processDeviceAddedInternal(DeviceId deviceId) {
-        // Irrespective of whether the local is a MASTER or not for this device,
-        // we need to create a SR-group-handler instance. This is because in a
-        // multi-instance setup, any instance can initiate forwarding/next-objectives
-        // for any switch (even if this instance is a SLAVE or not even connected
-        // to the switch). To handle this, a default-group-handler instance is necessary
-        // per switch.
-        log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
-        if (groupHandlerMap.get(deviceId) == null) {
-            DefaultGroupHandler groupHandler;
-            try {
-                groupHandler = DefaultGroupHandler.
-                        createGroupHandler(deviceId,
-                                appId,
-                                deviceConfiguration,
-                                linkService,
-                                flowObjectiveService,
-                                this);
-            } catch (DeviceConfigNotFoundException e) {
-                log.warn(e.getMessage() + " Aborting processDeviceAdded.");
-                return;
-            }
-            log.debug("updating groupHandlerMap with new grpHdlr for device: {}",
-                    deviceId);
-            groupHandlerMap.put(deviceId, groupHandler);
-        }
-
-        if (mastershipService.isLocalMaster(deviceId)) {
-            defaultRoutingHandler.populatePortAddressingRules(deviceId);
-            defaultRoutingHandler.purgeSeenBeforeRoutes(deviceId);
-            DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
-            groupHandler.createGroupsFromVlanConfig();
-            routingRulePopulator.populateSubnetBroadcastRule(deviceId);
-            phasedRecoveryService.init(deviceId);
-        }
-
-        appCfgHandler.init(deviceId);
-    }
-
-    private void processDeviceRemoved(Device device) {
-        dsNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(device.id()))
-                .forEach(entry -> dsNextObjStore.remove(entry.getKey()));
-        vlanNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(device.id()))
-                .forEach(entry -> vlanNextObjStore.remove(entry.getKey()));
-        macVlanNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(device.id()))
-                .forEach(entry -> macVlanNextObjStore.remove(entry.getKey()));
-        portNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(device.id()))
-                .forEach(entry -> portNextObjStore.remove(entry.getKey()));
-        linkHandler.processDeviceRemoved(device);
-
-        DefaultGroupHandler gh = groupHandlerMap.remove(device.id());
-        if (gh != null) {
-            gh.shutdown();
-        }
-        // Note that a switch going down is associated with all of its links
-        // going down as well, but it is treated as a single switch down event
-        // while the link-downs are ignored. We cannot rely on the ordering of
-        // events - i.e we cannot expect all link-downs to come before the
-        // switch down - so we purge all seen-links for the switch before
-        // handling route-path changes for the switch-down
-        defaultRoutingHandler
-            .populateRoutingRulesForLinkStatusChange(null, null, device.id(), true);
-        defaultRoutingHandler.purgeEcmpGraph(device.id());
-
-        // Cleanup all internal groupHandler stores for this device. Should be
-        // done after all rerouting or rehashing has been completed
-        groupHandlerMap.entrySet()
-            .forEach(entry -> entry.getValue().cleanUpForNeighborDown(device.id()));
-
-        phasedRecoveryService.reset(device.id());
-    }
-
-    /**
-     * Purge the destinationSet nextObjective store of entries with this device
-     * as key. Erases app-level knowledge of hashed groups in this device.
-     *
-     * @param devId the device identifier
-     */
-    void purgeHashedNextObjectiveStore(DeviceId devId) {
-        log.debug("Purging hashed next-obj store for dev:{}", devId);
-        dsNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(devId))
-                .forEach(entry -> dsNextObjStore.remove(entry.getKey()));
-    }
-
-    private void processPortUpdatedInternal(Device device, Port port) {
-        if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
-            log.warn("Device configuration uploading. Not handling port event for"
-                    + "dev: {} port: {}", device.id(), port.number());
-            return;
-        }
-
-        if (interfaceService.isConfigured(new ConnectPoint(device.id(), port.number()))) {
-            lastEdgePortEvent = Instant.now();
-        }
-
-        if (!mastershipService.isLocalMaster(device.id()))  {
-            log.debug("Not master for dev:{} .. not handling port updated event"
-                    + "for port {}", device.id(), port.number());
-            return;
-        }
-        processPortUpdated(device.id(), port);
-    }
-
-    /**
-     * Adds or remove filtering rules for the given switchport. If switchport is
-     * an edge facing port, additionally handles host probing and broadcast
-     * rules. Must be called by local master of device.
-     *
-     * @param deviceId the device identifier
-     * @param port the port to update
-     */
-    void processPortUpdated(DeviceId deviceId, Port port) {
-        // first we handle filtering rules associated with the port
-        if (port.isEnabled()) {
-            log.info("Switchport {}/{} enabled..programming filters",
-                     deviceId, port.number());
-            routingRulePopulator.processSinglePortFilters(deviceId, port.number(), true);
-        } else {
-            log.info("Switchport {}/{} disabled..removing filters",
-                     deviceId, port.number());
-            routingRulePopulator.processSinglePortFilters(deviceId, port.number(), false);
-        }
-
-        // portUpdated calls are for ports that have gone down or up. For switch
-        // to switch ports, link-events should take care of any re-routing or
-        // group editing necessary for port up/down. Here we only process edge ports
-        // that are already configured.
-        ConnectPoint cp = new ConnectPoint(deviceId, port.number());
-        VlanId untaggedVlan = interfaceService.getUntaggedVlanId(cp);
-        VlanId nativeVlan = interfaceService.getNativeVlanId(cp);
-        Set<VlanId> taggedVlans = interfaceService.getTaggedVlanId(cp);
-
-        if (untaggedVlan == null && nativeVlan == null && taggedVlans.isEmpty()) {
-            log.debug("Not handling port updated event for non-edge port (unconfigured) "
-                    + "dev/port: {}/{}", deviceId, port.number());
-            return;
-        }
-        if (untaggedVlan != null) {
-            processEdgePort(deviceId, port, untaggedVlan, true);
-        }
-        if (nativeVlan != null) {
-            processEdgePort(deviceId, port, nativeVlan, true);
-        }
-        if (!taggedVlans.isEmpty()) {
-            taggedVlans.forEach(tag -> processEdgePort(deviceId, port, tag, false));
-        }
-    }
-
-    private void processEdgePort(DeviceId deviceId, Port port, VlanId vlanId,
-                                 boolean popVlan) {
-        boolean portUp = port.isEnabled();
-        if (portUp) {
-            log.info("Device:EdgePort {}:{} is enabled in vlan: {}", deviceId,
-                     port.number(), vlanId);
-            hostEventExecutor.execute(() -> hostHandler.processPortUp(new ConnectPoint(deviceId, port.number())));
-        } else {
-            log.info("Device:EdgePort {}:{} is disabled in vlan: {}", deviceId,
-                     port.number(), vlanId);
-        }
-
-        DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
-        if (groupHandler != null) {
-            groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
-        } else {
-            log.warn("Group handler not found for dev:{}. Not handling edge port"
-                    + " {} event for port:{}", deviceId,
-                    (portUp) ? "UP" : "DOWN", port.number());
-        }
-    }
-
-    private void createOrUpdateDeviceConfiguration() {
-        if (deviceConfiguration == null) {
-            log.info("Creating new DeviceConfiguration");
-            deviceConfiguration = new DeviceConfiguration(this);
-        } else {
-            log.info("Updating DeviceConfiguration");
-            deviceConfiguration.updateConfig();
-        }
-    }
-
-    private void createOrUpdateDefaultRoutingHandler() {
-        if (defaultRoutingHandler == null) {
-            log.info("Creating new DefaultRoutingHandler");
-            defaultRoutingHandler = new DefaultRoutingHandler(this);
-        } else {
-            log.info("Updating DefaultRoutingHandler");
-            defaultRoutingHandler.update(this);
-        }
-    }
-
-    /**
-     * Registers the given connect point with the NRS, this is necessary
-     * to receive the NDP and ARP packets from the NRS.
-     *
-     * @param portToRegister connect point to register
-     */
-    public void registerConnectPoint(ConnectPoint portToRegister) {
-        neighbourResolutionService.registerNeighbourHandler(
-                portToRegister,
-                neighbourHandler,
-                appId
-        );
-    }
-
-    private class InternalConfigListener implements NetworkConfigListener {
-        private static final long PROGRAM_DELAY = 2;
-        SegmentRoutingManager srManager;
-
-        /**
-         * Constructs the internal network config listener.
-         *
-         * @param srManager segment routing manager
-         */
-        InternalConfigListener(SegmentRoutingManager srManager) {
-            this.srManager = srManager;
-        }
-
-        /**
-         * Reads network config and initializes related data structure accordingly.
-         */
-        void configureNetwork() {
-            log.info("Configuring network ...");
-
-            // Setting handling of network configuration events completable future
-            // The completable future is needed because of the async behaviour of the configureNetwork,
-            // listener registration and event arrival
-            // Enables us to buffer the events and execute them when the configure network is done.
-            synchronized (networkConfigCompletionLock) {
-                networkConfigCompletion = new CompletableFuture<>();
-
-                // add a small delay to absorb multiple network config added notifications
-                if (!programmingScheduled.get()) {
-                    log.info("Buffering config calls for {} secs", PROGRAM_DELAY);
-                    programmingScheduled.set(true);
-                    mainEventExecutor.schedule(new ConfigChange(), PROGRAM_DELAY, TimeUnit.SECONDS);
-                }
-
-                createOrUpdateDeviceConfiguration();
-
-                arpHandler = new ArpHandler(srManager);
-                icmpHandler = new IcmpHandler(srManager);
-                ipHandler = new IpHandler(srManager);
-                routingRulePopulator = new RoutingRulePopulator(srManager);
-                createOrUpdateDefaultRoutingHandler();
-
-                tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
-                    groupHandlerMap, tunnelStore);
-                policyHandler = new PolicyHandler(appId, deviceConfiguration,
-                    flowObjectiveService,
-                    tunnelHandler, policyStore);
-                networkConfigCompletion.complete(true);
-            }
-
-            mcastHandler.init();
-
-        }
-
-        @Override
-        public void event(NetworkConfigEvent event) {
-            if (mainEventExecutor == null) {
-                return;
-            }
-            checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
-            switch (event.type()) {
-                case CONFIG_ADDED:
-                case CONFIG_UPDATED:
-                case CONFIG_REMOVED:
-                    log.trace("Schedule Network Config event {}", event);
-                    if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
-                        mainEventExecutor.execute(new InternalEventHandler(event));
-                    } else {
-                        queuedEvents.add(event);
-                    }
-                    break;
-                default:
-                    break;
-            }
-        }
-
-        @Override
-        public boolean isRelevant(NetworkConfigEvent event) {
-            if (event.type() == CONFIG_REGISTERED ||
-                    event.type() == CONFIG_UNREGISTERED) {
-                log.debug("Ignore event {} due to type mismatch", event);
-                return false;
-            }
-
-            if (!event.configClass().equals(SegmentRoutingDeviceConfig.class) &&
-                    !event.configClass().equals(SegmentRoutingAppConfig.class) &&
-                    !event.configClass().equals(InterfaceConfig.class)) {
-                log.debug("Ignore event {} due to class mismatch", event);
-                return false;
-            }
-
-            return true;
-        }
-
-        private final class ConfigChange implements Runnable {
-            @Override
-            public void run() {
-                programmingScheduled.set(false);
-                log.info("Reacting to config changes after buffer delay");
-                for (Device device : deviceService.getDevices()) {
-                    processDeviceAdded(device);
-                }
-                defaultRoutingHandler.startPopulationProcess();
-            }
-        }
-    }
-
-    private class InternalLinkListener implements LinkListener {
-        @Override
-        public void event(LinkEvent event) {
-            if (mainEventExecutor == null) {
-                return;
-            }
-            if (event.type() == LinkEvent.Type.LINK_ADDED ||
-                    event.type() == LinkEvent.Type.LINK_UPDATED ||
-                    event.type() == LinkEvent.Type.LINK_REMOVED) {
-                log.trace("Schedule Link event {}", event);
-                if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
-                    mainEventExecutor.execute(new InternalEventHandler(event));
-                } else {
-                    queuedEvents.add(event);
-                }
-            }
-        }
-    }
-
-    private class InternalDeviceListener implements DeviceListener {
-        @Override
-        public void event(DeviceEvent event) {
-            if (mainEventExecutor == null) {
-                return;
-            }
-            switch (event.type()) {
-                case DEVICE_ADDED:
-                case PORT_UPDATED:
-                case PORT_ADDED:
-                case DEVICE_UPDATED:
-                case DEVICE_AVAILABILITY_CHANGED:
-                    log.trace("Schedule Device event {}", event);
-                    if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
-                        mainEventExecutor.execute(new InternalEventHandler(event));
-                    } else {
-                        queuedEvents.add(event);
-                    }
-                    break;
-                default:
-            }
-        }
-    }
-
-    private class InternalTopologyListener implements TopologyListener {
-        @Override
-        public void event(TopologyEvent event) {
-            if (mainEventExecutor == null) {
-                return;
-            }
-            switch (event.type()) {
-                case TOPOLOGY_CHANGED:
-                    log.trace("Schedule Topology event {}", event);
-                    if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
-                        mainEventExecutor.execute(new InternalEventHandler(event));
-                    } else {
-                        queuedEvents.add(event);
-                    }
-                    break;
-                default:
-            }
-        }
-    }
-
-    private class InternalHostListener implements HostListener {
-        @Override
-        public void event(HostEvent event) {
-            if (hostEventExecutor == null) {
-                return;
-            }
-            switch (event.type()) {
-                case HOST_ADDED:
-                case HOST_MOVED:
-                case HOST_REMOVED:
-                case HOST_UPDATED:
-                    log.trace("Schedule Host event {}", event);
-                    hostEventExecutor.execute(new InternalEventHandler(event));
-                    break;
-                default:
-                    log.warn("Unsupported host event type: {}", event.type());
-                    break;
-            }
-        }
-    }
-
-    private class InternalMcastListener implements McastListener {
-        @Override
-        public void event(McastEvent event) {
-            if (mcastEventExecutor == null) {
-                return;
-            }
-            switch (event.type()) {
-                case SOURCES_ADDED:
-                case SOURCES_REMOVED:
-                case SINKS_ADDED:
-                case SINKS_REMOVED:
-                case ROUTE_REMOVED:
-                case ROUTE_ADDED:
-                    log.trace("Schedule Mcast event {}", event);
-                    mcastEventExecutor.execute(new InternalEventHandler(event));
-                    break;
-                default:
-                    log.warn("Unsupported mcast event type: {}", event.type());
-                    break;
-            }
-        }
-    }
-
-    private class InternalRouteEventListener implements RouteListener {
-        @Override
-        public void event(RouteEvent event) {
-            if (routeEventExecutor == null) {
-                return;
-            }
-            switch (event.type()) {
-                case ROUTE_ADDED:
-                case ROUTE_UPDATED:
-                case ROUTE_REMOVED:
-                case ALTERNATIVE_ROUTES_CHANGED:
-                    log.trace("Schedule Route event {}", event);
-                    routeEventExecutor.execute(new InternalEventHandler(event));
-                    break;
-                default:
-                    log.warn("Unsupported route event type: {}", event.type());
-                    break;
-            }
-        }
-    }
-
-    private class InternalMastershipListener implements MastershipListener {
-        @Override
-        public void event(MastershipEvent event) {
-            if (mainEventExecutor == null) {
-                return;
-            }
-            switch (event.type()) {
-            case MASTER_CHANGED:
-                log.debug("Mastership event: {}/{}", event.subject(),
-                          event.roleInfo());
-                mainEventExecutor.execute(new InternalEventHandler(event));
-                break;
-            case BACKUPS_CHANGED:
-            case SUSPENDED:
-            default:
-                log.debug("Mastership event type {} not handled", event.type());
-                break;
-            }
-        }
-    }
-
-    class InternalClusterListener implements ClusterEventListener {
-        private Instant lastClusterEvent = Instant.EPOCH;
-
-        long timeSinceLastClusterEvent() {
-            return Instant.now().toEpochMilli() - lastClusterEvent.toEpochMilli();
-        }
-
-        @Override
-        public void event(ClusterEvent event) {
-            switch (event.type()) {
-            case INSTANCE_ACTIVATED:
-            case INSTANCE_ADDED:
-            case INSTANCE_READY:
-                log.debug("Cluster event {} ignored", event.type());
-                break;
-            case INSTANCE_DEACTIVATED:
-            case INSTANCE_REMOVED:
-                log.info("** Cluster event {}", event.type());
-                lastClusterEvent = Instant.now();
-                break;
-            default:
-                break;
-            }
-
-        }
-
-    }
-
-    private void updateInterface(InterfaceConfig conf, InterfaceConfig prevConf) {
-        try {
-            Set<Interface> intfs = conf.getInterfaces();
-            Set<Interface> prevIntfs = prevConf.getInterfaces();
-
-            // Now we only handle one interface config at each port.
-            if (intfs.size() != 1 || prevIntfs.size() != 1) {
-                log.warn("Interface update aborted - one at a time is allowed, " +
-                                 "but {} / {}(prev) received.", intfs.size(), prevIntfs.size());
-                return;
-            }
-
-            //The system is in an incoherent state, abort
-            if (defaultRoutingHandler == null) {
-                log.warn("Interface update aborted, defaultRoutingHandler is null");
-                return;
-            }
-
-            Interface intf = intfs.stream().findFirst().get();
-            Interface prevIntf = prevIntfs.stream().findFirst().get();
-
-            DeviceId deviceId = intf.connectPoint().deviceId();
-            PortNumber portNum = intf.connectPoint().port();
-
-            removeSubnetConfig(prevIntf.connectPoint(),
-                               Sets.difference(new HashSet<>(prevIntf.ipAddressesList()),
-                                               new HashSet<>(intf.ipAddressesList())));
-
-            if (!prevIntf.vlanNative().equals(VlanId.NONE)
-                    && !prevIntf.vlanNative().equals(intf.vlanUntagged())
-                    && !prevIntf.vlanNative().equals(intf.vlanNative())) {
-                if (intf.vlanTagged().contains(prevIntf.vlanNative())) {
-                    // Update filtering objective and L2IG group bucket
-                    updatePortVlanTreatment(deviceId, portNum, prevIntf.vlanNative(), false);
-                } else {
-                    // RemoveVlanNative
-                    updateVlanConfigInternal(deviceId, portNum, prevIntf.vlanNative(), true, false);
-                }
-            }
-
-            if (!prevIntf.vlanUntagged().equals(VlanId.NONE)
-                    && !prevIntf.vlanUntagged().equals(intf.vlanUntagged())
-                    && !prevIntf.vlanUntagged().equals(intf.vlanNative())) {
-                if (intf.vlanTagged().contains(prevIntf.vlanUntagged())) {
-                    // Update filtering objective and L2IG group bucket
-                    updatePortVlanTreatment(deviceId, portNum, prevIntf.vlanUntagged(), false);
-                } else {
-                    // RemoveVlanUntagged
-                    updateVlanConfigInternal(deviceId, portNum, prevIntf.vlanUntagged(), true, false);
-                }
-            }
-
-            if (!prevIntf.vlanTagged().isEmpty() && !intf.vlanTagged().equals(prevIntf.vlanTagged())) {
-                // RemoveVlanTagged
-                Sets.difference(prevIntf.vlanTagged(), intf.vlanTagged()).stream()
-                        .filter(i -> !intf.vlanUntagged().equals(i))
-                        .filter(i -> !intf.vlanNative().equals(i))
-                        .forEach(vlanId -> updateVlanConfigInternal(
-                                deviceId, portNum, vlanId, false, false));
-            }
-
-            if (!intf.vlanNative().equals(VlanId.NONE)
-                    && !prevIntf.vlanNative().equals(intf.vlanNative())
-                    && !prevIntf.vlanUntagged().equals(intf.vlanNative())) {
-                if (prevIntf.vlanTagged().contains(intf.vlanNative())) {
-                    // Update filtering objective and L2IG group bucket
-                    updatePortVlanTreatment(deviceId, portNum, intf.vlanNative(), true);
-                } else {
-                    // AddVlanNative
-                    updateVlanConfigInternal(deviceId, portNum, intf.vlanNative(), true, true);
-                }
-            }
-
-            if (!intf.vlanTagged().isEmpty() && !intf.vlanTagged().equals(prevIntf.vlanTagged())) {
-                // AddVlanTagged
-                Sets.difference(intf.vlanTagged(), prevIntf.vlanTagged()).stream()
-                        .filter(i -> !prevIntf.vlanUntagged().equals(i))
-                        .filter(i -> !prevIntf.vlanNative().equals(i))
-                        .forEach(vlanId -> updateVlanConfigInternal(
-                                deviceId, portNum, vlanId, false, true)
-                );
-            }
-
-            if (!intf.vlanUntagged().equals(VlanId.NONE)
-                    && !prevIntf.vlanUntagged().equals(intf.vlanUntagged())
-                    && !prevIntf.vlanNative().equals(intf.vlanUntagged())) {
-                if (prevIntf.vlanTagged().contains(intf.vlanUntagged())) {
-                    // Update filtering objective and L2IG group bucket
-                    updatePortVlanTreatment(deviceId, portNum, intf.vlanUntagged(), true);
-                } else {
-                    // AddVlanUntagged
-                    updateVlanConfigInternal(deviceId, portNum, intf.vlanUntagged(), true, true);
-                }
-            }
-            addSubnetConfig(prevIntf.connectPoint(),
-                            Sets.difference(new HashSet<>(intf.ipAddressesList()),
-                                            new HashSet<>(prevIntf.ipAddressesList())));
-        } catch (ConfigException e) {
-            log.error("Error in configuration");
-        }
-    }
-
-    private void updatePortVlanTreatment(DeviceId deviceId, PortNumber portNum,
-                                         VlanId vlanId, boolean pushVlan) {
-        DefaultGroupHandler grpHandler = getGroupHandler(deviceId);
-        if (grpHandler == null) {
-            log.warn("Failed to retrieve group handler for device {}", deviceId);
-            return;
-        }
-
-        // Update filtering objective for a single port
-        routingRulePopulator.updateSinglePortFilters(deviceId, portNum, !pushVlan, vlanId, false);
-        routingRulePopulator.updateSinglePortFilters(deviceId, portNum, pushVlan, vlanId, true);
-
-        if (getVlanNextObjectiveId(deviceId, vlanId) != -1) {
-            // Update L2IG bucket of the port
-            grpHandler.updateL2InterfaceGroupBucket(portNum, vlanId, pushVlan);
-            // Update bridging and unicast routing rule for each host
-            hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
-                    vlanId, !pushVlan, false));
-            hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
-                    vlanId, pushVlan, true));
-        } else {
-            log.warn("Failed to retrieve next objective for vlan {} in device {}:{}", vlanId, deviceId, portNum);
-        }
-    }
-
-    private void updateVlanConfigInternal(DeviceId deviceId, PortNumber portNum,
-                                          VlanId vlanId, boolean pushVlan, boolean install) {
-        DefaultGroupHandler grpHandler = getGroupHandler(deviceId);
-        if (grpHandler == null) {
-            log.warn("Failed to retrieve group handler for device {}", deviceId);
-            return;
-        }
-
-        // Update filtering objective for a single port
-        routingRulePopulator.updateSinglePortFilters(deviceId, portNum, pushVlan, vlanId, install);
-
-        // Update filtering objective for multicast ingress port
-        mcastHandler.updateFilterToDevice(deviceId, portNum, vlanId, install);
-
-        int nextId = getVlanNextObjectiveId(deviceId, vlanId);
-
-        if (nextId != -1 && !install) {
-            // Remove L2 Bridging rule and L3 Unicast rule to the host
-            hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
-                    vlanId, pushVlan, install));
-            // Remove broadcast forwarding rule and corresponding L2FG for VLAN
-            // only if there is no port configured on that VLAN ID
-            if (!getVlanPortMap(deviceId).containsKey(vlanId)) {
-                // Remove broadcast forwarding rule for the VLAN
-                routingRulePopulator.updateSubnetBroadcastRule(deviceId, vlanId, install);
-                // Remove L2FG for VLAN
-                grpHandler.removeBcastGroupFromVlan(deviceId, portNum, vlanId, pushVlan);
-            } else {
-                // Remove a single port from L2FG
-                grpHandler.updateGroupFromVlanConfiguration(vlanId, portNum, nextId, install);
-            }
-            // Remove L2IG of the port
-            grpHandler.removePortNextObjective(deviceId, portNum, vlanId, pushVlan);
-        } else if (install) {
-            // Create L2IG of the port
-            grpHandler.createPortNextObjective(deviceId, portNum, vlanId, pushVlan);
-            // Create L2 Bridging rule and L3 Unicast rule to the host
-            hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
-                    vlanId, pushVlan, install));
-            if (nextId != -1) {
-                // Add a single port to L2FG
-                grpHandler.updateGroupFromVlanConfiguration(vlanId, portNum, nextId, install);
-            } else {
-                // Create L2FG for VLAN
-                grpHandler.createBcastGroupFromVlan(vlanId, Collections.singleton(portNum));
-                routingRulePopulator.updateSubnetBroadcastRule(deviceId, vlanId, install);
-            }
-        } else {
-            log.warn("Failed to retrieve next objective for vlan {} in device {}:{}", vlanId, deviceId, portNum);
-        }
-    }
-
-    private void removeSubnetConfig(ConnectPoint cp, Set<InterfaceIpAddress> ipAddressSet) {
-        Set<IpPrefix> ipPrefixSet = ipAddressSet.stream().
-                map(InterfaceIpAddress::subnetAddress).collect(Collectors.toSet());
-
-        Set<InterfaceIpAddress> deviceIntfIpAddrs = interfaceService.getInterfaces().stream()
-                .filter(intf -> intf.connectPoint().deviceId().equals(cp.deviceId()))
-                .filter(intf -> !intf.connectPoint().equals(cp))
-                .flatMap(intf -> intf.ipAddressesList().stream())
-                .collect(Collectors.toSet());
-        // 1. Partial subnet population
-        // Remove routing rules for removed subnet from previous configuration,
-        // which does not also exist in other interfaces in the same device
-        Set<IpPrefix> deviceIpPrefixSet = deviceIntfIpAddrs.stream()
-                .map(InterfaceIpAddress::subnetAddress)
-                .collect(Collectors.toSet());
-
-        Set<IpPrefix> subnetsToBeRevoked = ipPrefixSet.stream()
-                .filter(ipPrefix -> !deviceIpPrefixSet.contains(ipPrefix))
-                .collect(Collectors.toSet());
-
-        // Check if any of the subnets to be revoked is configured in the pairDevice.
-        // If any, repopulate the subnet with pairDevice connectPoint instead of revoking.
-        Optional<DeviceId> pairDevice = getPairDeviceId(cp.deviceId());
-        if (pairDevice.isPresent()) {
-            Set<IpPrefix> pairDeviceIpPrefix = getDeviceSubnetMap().get(pairDevice.get());
-
-            Set<IpPrefix> subnetsExistingInPairDevice = subnetsToBeRevoked.stream()
-                    .filter(ipPrefix -> pairDeviceIpPrefix.contains(ipPrefix))
-                    .collect(Collectors.toSet());
-
-            // Update the subnets existing in pair device with pair device connect point.
-            if (!subnetsExistingInPairDevice.isEmpty()) {
-                // PortNumber of connect point is not relevant in populate subnet and hence providing as ANY.
-                ConnectPoint pairDeviceCp = new ConnectPoint(pairDevice.get(), PortNumber.ANY);
-                log.debug("Updating the subnets: {} with pairDevice connectPoint as it exists in the Pair device: {}",
-                        subnetsExistingInPairDevice, pairDeviceCp);
-                defaultRoutingHandler.populateSubnet(Collections.singleton(pairDeviceCp), subnetsExistingInPairDevice);
-            }
-
-            // Remove only the subnets that are not configured in the pairDevice.
-            subnetsToBeRevoked = Sets.difference(subnetsToBeRevoked, subnetsExistingInPairDevice);
-        }
-
-        if (!subnetsToBeRevoked.isEmpty()) {
-            log.debug("Removing subnets for connectPoint: {}, subnets: {}", cp, subnetsToBeRevoked);
-            defaultRoutingHandler.revokeSubnet(subnetsToBeRevoked);
-        }
-
-        // 2. Interface IP punts
-        // Remove IP punts for old Intf address
-        Set<IpAddress> deviceIpAddrs = deviceIntfIpAddrs.stream()
-                .map(InterfaceIpAddress::ipAddress)
-                .collect(Collectors.toSet());
-        ipAddressSet.stream()
-                .map(InterfaceIpAddress::ipAddress)
-                .filter(interfaceIpAddress -> !deviceIpAddrs.contains(interfaceIpAddress))
-                .forEach(interfaceIpAddress ->
-                                 routingRulePopulator.revokeSingleIpPunts(
-                                         cp.deviceId(), interfaceIpAddress));
-
-        // 3. Host unicast routing rule
-        // Remove unicast routing rule
-        hostEventExecutor.execute(() -> hostHandler.processIntfIpUpdatedEvent(cp, ipPrefixSet, false));
-    }
-
-    private void addSubnetConfig(ConnectPoint cp, Set<InterfaceIpAddress> ipAddressSet) {
-        Set<IpPrefix> ipPrefixSet = ipAddressSet.stream().
-                map(InterfaceIpAddress::subnetAddress).collect(Collectors.toSet());
-
-        Set<InterfaceIpAddress> deviceIntfIpAddrs = interfaceService.getInterfaces().stream()
-                .filter(intf -> intf.connectPoint().deviceId().equals(cp.deviceId()))
-                .filter(intf -> !intf.connectPoint().equals(cp))
-                .flatMap(intf -> intf.ipAddressesList().stream())
-                .collect(Collectors.toSet());
-        // 1. Partial subnet population
-        // Add routing rules for newly added subnet, which does not also exist in
-        // other interfaces in the same device
-        Set<IpPrefix> deviceIpPrefixSet = deviceIntfIpAddrs.stream()
-                .map(InterfaceIpAddress::subnetAddress)
-                .collect(Collectors.toSet());
-        Set<IpPrefix> subnetsToBePopulated = ipPrefixSet.stream()
-                .filter(ipPrefix -> !deviceIpPrefixSet.contains(ipPrefix))
-                .collect(Collectors.toSet());
-
-        if (!subnetsToBePopulated.isEmpty()) {
-            log.debug("Adding subnets for connectPoint: {}, subnets: {}", cp, subnetsToBePopulated);
-
-            // check if pair-device has the same subnet configured?
-            Optional<DeviceId> pairDevice = getPairDeviceId(cp.deviceId());
-            if (pairDevice.isPresent()) {
-                Set<IpPrefix> pairDeviceIpPrefix = getDeviceSubnetMap().get(pairDevice.get());
-
-                Set<IpPrefix>  subnetsToBePopulatedAsDualHomed = subnetsToBePopulated.stream()
-                        .filter(ipPrefix -> pairDeviceIpPrefix.contains(ipPrefix))
-                        .collect(Collectors.toSet());
-                Set<IpPrefix> subnetsToBePopulatedAsSingleHomed = Sets.difference(subnetsToBePopulated,
-                        subnetsToBePopulatedAsDualHomed);
-
-                if (!subnetsToBePopulatedAsSingleHomed.isEmpty()) {
-                    defaultRoutingHandler.populateSubnet(
-                            Collections.singleton(cp),
-                            subnetsToBePopulatedAsSingleHomed);
-                }
-
-                if (!subnetsToBePopulatedAsDualHomed.isEmpty()) {
-                    Set<ConnectPoint> cpts = new HashSet<>();
-                    cpts.add(cp);
-                    // As Subnets is DualHomed adding the pairDevice also as ConnectPoint.
-                    // PortNumber of connect point is not relevant in populate subnet and hence providing as ANY.
-                    ConnectPoint pairCp = new ConnectPoint(pairDevice.get(), PortNumber.ANY);
-                    cpts.add(pairCp);
-
-                    log.debug("Adding DualHomed subnets for connectPoint: {} and its pair device: {}, subnets: {}",
-                            cp, pairCp, subnetsToBePopulatedAsDualHomed);
-
-                    // populating the subnets as DualHomed
-                    defaultRoutingHandler.populateSubnet(
-                            cpts,
-                            subnetsToBePopulated);
-
-                    // revoking the subnets populated in the device as it is now Dualhomed.
-                    defaultRoutingHandler.revokeSubnet(Collections.singleton(cp.deviceId()),
-                            subnetsToBePopulatedAsDualHomed);
-                }
-            } else {
-                defaultRoutingHandler.populateSubnet(
-                        Collections.singleton(cp),
-                        subnetsToBePopulated);
-            }
-        }
-
-        // 2. Interface IP punts
-        // Add IP punts for new Intf address
-        Set<IpAddress> deviceIpAddrs = deviceIntfIpAddrs.stream()
-                .map(InterfaceIpAddress::ipAddress)
-                .collect(Collectors.toSet());
-        ipAddressSet.stream()
-                .map(InterfaceIpAddress::ipAddress)
-                .filter(interfaceIpAddress -> !deviceIpAddrs.contains(interfaceIpAddress))
-                .forEach(interfaceIpAddress ->
-                                 routingRulePopulator.populateSingleIpPunts(
-                                         cp.deviceId(), interfaceIpAddress));
-
-        // 3. Host unicast routing rule
-        // Add unicast routing rule
-        hostEventExecutor.execute(() -> hostHandler.processIntfIpUpdatedEvent(cp, ipPrefixSet, true));
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java
deleted file mode 100644
index 3cf0e32..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2016-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 org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.neighbour.NeighbourMessageHandler;
-import org.onosproject.net.host.HostService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This handler dispatches to the appropriate handlers the
- * neighbour discovery protocols.
- */
-public class SegmentRoutingNeighbourDispatcher implements NeighbourMessageHandler {
-
-    private static Logger log = LoggerFactory.getLogger(SegmentRoutingNeighbourDispatcher.class);
-    private SegmentRoutingManager manager;
-
-    /**
-     * Create a segment routing neighbour dispatcher.
-     *
-     * @param segmentRoutingManager the segment routing manager
-     */
-    public SegmentRoutingNeighbourDispatcher(SegmentRoutingManager segmentRoutingManager) {
-        this.manager = segmentRoutingManager;
-    }
-
-    @Override
-    public void handleMessage(NeighbourMessageContext context, HostService hostService) {
-        manager.neighborExecutor.execute(() -> handleMessageInternal(context, hostService));
-    }
-
-    private void handleMessageInternal(NeighbourMessageContext context, HostService hostService) {
-        log.trace("Received {} packet on {}: {}", context.protocol(),
-                  context.inPort(), context.packet());
-        switch (context.protocol()) {
-            case ARP:
-                if (this.manager.arpHandler != null) {
-                    this.manager.arpHandler.processPacketIn(context, hostService);
-                }
-                break;
-            case NDP:
-                if (this.manager.icmpHandler != null) {
-                    this.manager.icmpHandler.processPacketIn(context, hostService);
-                }
-                break;
-            default:
-                log.warn("Unknown protocol", context.protocol());
-        }
-    }
-
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java
deleted file mode 100644
index 8ef8e7e..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2016-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 org.onlab.packet.Ethernet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * This handler provides provides useful functions to the
- * neighbour handlers (ARP, NDP).
- */
-public class SegmentRoutingNeighbourHandler {
-
-    private static Logger log = LoggerFactory.getLogger(SegmentRoutingNeighbourHandler.class);
-
-    protected SegmentRoutingManager srManager;
-    protected DeviceConfiguration config;
-
-    /**
-     * Creates an SegmentRoutingNeighbourHandler object.
-     *
-     * @param srManager SegmentRoutingManager object
-     */
-    public SegmentRoutingNeighbourHandler(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-        this.config = checkNotNull(srManager.deviceConfiguration);
-    }
-
-    /**
-     * Creates an SegmentRoutingNeighbourHandler object.
-     */
-    public SegmentRoutingNeighbourHandler() {
-        this.srManager = null;
-        this.config = null;
-    }
-
-    /**
-     * Retrieve router (device) info.
-     *
-     * @param mac where to copy the mac
-     * @param ip where to copy the ip
-     * @param deviceId the device id
-     * @param targetAddress the target address
-     * @return true if it was possible to get the necessary info.
-     * False for errors
-     */
-    protected boolean getSenderInfo(byte[] mac,
-                                 byte[] ip,
-                                 DeviceId deviceId,
-                                 IpAddress targetAddress) {
-        byte[] senderMacAddress;
-        byte[] senderIpAddress;
-        IpAddress sender;
-        try {
-            senderMacAddress = config.getDeviceMac(deviceId).toBytes();
-            if (targetAddress.isIp4()) {
-                sender = config.getRouterIpAddressForASubnetHost(targetAddress.getIp4Address());
-            } else {
-                sender = config.getRouterIpAddressForASubnetHost(targetAddress.getIp6Address());
-            }
-            // If sender is null we abort.
-            if (sender == null) {
-                log.warn("Sender ip is null. Aborting getSenderInfo");
-                return false;
-            }
-            senderIpAddress = sender.toOctets();
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting getSenderInfo");
-            return false;
-        }
-        System.arraycopy(senderMacAddress, 0, mac, 0, senderMacAddress.length);
-        System.arraycopy(senderIpAddress, 0, ip, 0, senderIpAddress.length);
-        return true;
-    }
-
-    /**
-     * Reads the boolean configuration for responding to unknown hosts.
-     *
-     * @return respondToUnknownHosts boolean.
-     */
-    protected boolean respondToUnknownHosts() {
-        return srManager.respondToUnknownHosts;
-    }
-
-    /**
-     * Utility to send a ND reply using the supplied information.
-     *
-     * @param pkt the request
-     * @param targetMac the target mac
-     * @param hostService the host service
-     * @param isRouter true if this reply is sent on behalf of a router
-     */
-    protected void sendResponse(NeighbourMessageContext pkt, MacAddress targetMac, HostService hostService,
-                                boolean isRouter) {
-        // if this is false, check if host exists in the store
-        if (!respondToUnknownHosts()) {
-            short vlanId = pkt.packet().getQinQVID();
-            HostId dstId = HostId.hostId(pkt.srcMac(), vlanId == Ethernet.VLAN_UNTAGGED
-                    ? pkt.vlan() : VlanId.vlanId(vlanId));
-            Host dst = hostService.getHost(dstId);
-            if (dst == null) {
-                log.warn("Cannot send {} response to host {} - does not exist in the store",
-                         pkt.protocol(), dstId);
-                return;
-            }
-        }
-        pkt.setIsRouter(isRouter);
-        pkt.reply(targetMac);
-    }
-
-    /**
-     * Flood to all ports in the same subnet.
-     *
-     * @param packet packet to be flooded
-     * @param inPort where the packet comes from
-     * @param targetAddress the target address
-     */
-    protected void flood(Ethernet packet, ConnectPoint inPort, IpAddress targetAddress) {
-        try {
-            srManager.deviceConfiguration
-                    .getSubnetPortsMap(inPort.deviceId()).forEach((subnet, ports) -> {
-                if (subnet.contains(targetAddress)) {
-                    ports.stream()
-                            .filter(port -> port != inPort.port())
-                            .forEach(port -> {
-                                forward(packet, new ConnectPoint(inPort.deviceId(), port));
-                            });
-                }
-            });
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage()
-                             + " Cannot flood in subnet as device config not available"
-                             + " for device: " + inPort.deviceId());
-        }
-    }
-
-    /*
-     * Floods only on the port which have been configured with the subnet
-     * of the target address. The in port is excluded.
-     *
-     * @param pkt the ndp/arp packet and context information
-     */
-    protected void flood(NeighbourMessageContext pkt) {
-        try {
-            srManager.deviceConfiguration
-                    .getSubnetPortsMap(pkt.inPort().deviceId()).forEach((subnet, ports) -> {
-                if (subnet.contains(pkt.target())) {
-                    ports.stream()
-                            .filter(port -> port != pkt.inPort().port())
-                            .forEach(port -> {
-                                ConnectPoint outPoint = new ConnectPoint(
-                                        pkt.inPort().deviceId(),
-                                        port
-                                );
-                                pkt.forward(outPoint);
-                            });
-                }
-            });
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage()
-                             + " Cannot flood in subnet as device config not available"
-                             + " for device: " + pkt.inPort().deviceId());
-        }
-    }
-
-    /**
-     * Packet out to given port.
-     *
-     * Note: In current implementation, we expect all communication with
-     * end hosts within a subnet to be untagged.
-     * <p>
-     * For those pipelines that internally assigns a VLAN, the VLAN tag will be
-     * removed before egress.
-     * <p>
-     * For those pipelines that do not assign internal VLAN, the packet remains
-     * untagged.
-     *
-     * @param packet packet to be forwarded
-     * @param outPort where the packet should be forwarded
-     */
-    private void forward(Ethernet packet, ConnectPoint outPort) {
-        ByteBuffer buf = ByteBuffer.wrap(packet.serialize());
-
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.setOutput(outPort.port());
-        srManager.packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
-                                                               tbuilder.build(), buf));
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
deleted file mode 100644
index 3bfd88b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * 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.Multimap;
-import org.apache.commons.lang3.NotImplementedException;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
-import org.onosproject.segmentrouting.mcast.McastFilteringObjStoreKey;
-import org.onosproject.segmentrouting.mcast.McastRole;
-import org.onosproject.segmentrouting.mcast.McastRoleStoreKey;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.segmentrouting.mcast.McastStoreKey;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * Segment Routing Service for REST API.
- */
-public interface SegmentRoutingService {
-    /**
-     * VLAN cross-connect ACL priority.
-     *
-     * @deprecated in ONOS 1.12. Replaced by {@link org.onosproject.segmentrouting.xconnect.api.XconnectService}
-     */
-    @Deprecated
-    int XCONNECT_ACL_PRIORITY = 60000;
-
-    /**
-     * VLAN cross-connect Bridging priority.
-     *
-     * @deprecated in ONOS 1.12. Replaced by {@link org.onosproject.segmentrouting.xconnect.api.XconnectService}
-     */
-    @Deprecated
-    int XCONNECT_PRIORITY = 1000;
-
-    /**
-     * Default flow priority.
-     */
-    int DEFAULT_PRIORITY = 100;
-
-    /**
-     * Minimum IP priority.
-     *
-     * Should &lt; 0 such that priority of /0 will not conflict with lowest
-     * priority default entries.
-     */
-    int MIN_IP_PRIORITY = 10;
-
-    /**
-     * Subnet flooding flow priority.
-     */
-    int FLOOD_PRIORITY = 5;
-
-    /**
-     * Returns all tunnels.
-     *
-     * @return list of tunnels
-     */
-    List<Tunnel> getTunnels();
-
-    /**
-     * Creates a tunnel.
-     *
-     * @param tunnel tunnel reference to create
-     * @return WRONG_PATH if the tunnel path is wrong, ID_EXISTS if the tunnel ID
-     * exists already, TUNNEL_EXISTS if the same tunnel exists, INTERNAL_ERROR
-     * if the tunnel creation failed internally, SUCCESS if the tunnel is created
-     * successfully
-     */
-    TunnelHandler.Result createTunnel(Tunnel tunnel);
-
-    /**
-     * Returns all policies.
-     *
-     * @return list of policy
-     */
-    List<Policy> getPolicies();
-
-    /**
-     * Returns the l2 tunnel descriptions.
-     *
-     * @param pending if true fetch pending pseudowires, else fetch installed
-     * @return set of l2 tunnel descriptions.
-     */
-    Set<L2TunnelDescription> getL2TunnelDescriptions(boolean pending);
-
-    /**
-     * Returns all l2 tunnels of pseudowires.
-     *
-     * @return list of l2 tunnels
-     */
-    List<L2Tunnel> getL2Tunnels();
-
-    /**
-     * Returns all l2 policie of pseudowires.
-     *
-     * @return list of l2 policies.
-     */
-    List<L2TunnelPolicy> getL2Policies();
-
-    /**
-     * Removes pseudowire.
-     *
-     * @param pwId The id of the pseudowire.
-     * @return SUCCESS if operation successful or a descriptive error otherwise.
-     */
-    L2TunnelHandler.Result removePseudowire(Integer pwId);
-
-    /**
-     * Adds a Pseudowire to the system.
-     *
-     * @param tunnel The pseudowire tunnel.
-     * @return SUCCESS if operation is successful or a descriptive error otherwise.
-     */
-    L2TunnelHandler.Result addPseudowire(L2TunnelDescription tunnel);
-
-    /**
-     * Adds a set of pseudowires.
-     *
-     *
-     * @param l2TunnelDescriptions The pseudowires to add.
-     * @return SUCCESS if ALL pseudowires can be instantiated and are deployed, or a
-     *         a descriptive error otherwise, without deploying any pseudowire.
-     * @deprecated onos-1.12 use addPseudowire instead
-     */
-    @Deprecated
-    L2TunnelHandler.Result addPseudowiresBulk(List<DefaultL2TunnelDescription> l2TunnelDescriptions);
-
-    /**
-     * Creates a policy.
-     *
-     * @param policy policy reference to create
-     * @return ID_EXISTS if the same policy ID exists,
-     *  POLICY_EXISTS if the same policy exists, TUNNEL_NOT_FOUND if the tunnel
-     *  does not exists, UNSUPPORTED_TYPE if the policy type is not supported,
-     *  SUCCESS if the policy is created successfully.
-     */
-    PolicyHandler.Result createPolicy(Policy policy);
-
-    /**
-     * Removes a tunnel.
-     *
-     * @param tunnel tunnel reference to remove
-     * @return TUNNEL_NOT_FOUND if the tunnel to remove does not exists,
-     * INTERNAL_ERROR if the tunnel creation failed internally, SUCCESS
-     * if the tunnel is created successfully.
-     */
-    TunnelHandler.Result removeTunnel(Tunnel tunnel);
-
-    /**
-     * Removes a policy.
-     *
-     * @param policy policy reference to remove
-     * @return POLICY_NOT_FOUND if the policy to remove does not exists,
-     * SUCCESS if it is removed successfully
-     */
-    PolicyHandler.Result removePolicy(Policy policy);
-
-    /**
-     * Use current state of the network to repopulate forwarding rules.
-     *
-     */
-    void rerouteNetwork();
-
-    /**
-     * Returns device-subnet mapping.
-     *
-     * @return device-subnet mapping
-     */
-    Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap();
-
-    /**
-     * Returns the current ECMP shortest path graph in this controller instance.
-     *
-     * @return ECMP shortest path graph
-     */
-    ImmutableMap<DeviceId, EcmpShortestPathGraph> getCurrentEcmpSpg();
-
-    /**
-     * Returns the destinatiomSet-NextObjective store contents.
-     *
-     * @return current contents of the dstNextObjStore
-     */
-    ImmutableMap<DestinationSetNextObjectiveStoreKey, NextNeighbors> getDstNextObjStore();
-
-    /**
-     * Returns the VLAN next objective store.
-     *
-     * @return current contents of the vlanNextObjStore
-     */
-    ImmutableMap<VlanNextObjectiveStoreKey, Integer> getVlanNextObjStore();
-
-    /**
-     * Returns the Mac Vlan next objective store.
-     *
-     * @return current contents of the macVlanNextObjStore
-     */
-    ImmutableMap<MacVlanNextObjectiveStoreKey, Integer> getMacVlanNextObjStore();
-
-    /**
-     * Returns the port next objective store.
-     *
-     * @return current contents of the portNextObjStore
-     */
-    ImmutableMap<PortNextObjectiveStoreKey, Integer> getPortNextObjStore();
-
-    /**
-     * Returns the associated next ids to the mcast groups or to the single
-     * group if mcastIp is present.
-     *
-     * @param mcastIp the group ip
-     * @return the mapping mcastIp-device to next id
-     */
-    Map<McastStoreKey, Integer> getMcastNextIds(IpAddress mcastIp);
-
-    /**
-     * Returns the PW init next objective store.
-     *
-     * @return current contents of the l2InitiationNextObjStore
-     */
-    ImmutableMap<String, NextObjective> getPwInitNext();
-
-    /**
-     * Returns the PW termination next objective store.
-     *
-     * @return current contents of the l2TerminationNextObjStore
-     */
-    ImmutableMap<String, NextObjective> getPwTermNext();
-
-    /**
-     * Removes all entries in dst/vlan/port/mcast NextObjectiveStore that are associated with the given nextId.
-     *
-     * @param nextId nextId
-     */
-    void invalidateNextObj(int nextId);
-
-    /**
-     * Triggers the verification of all ECMP groups in the specified device.
-     * Adjusts the group buckets if verification finds that there are more or less
-     * buckets than what should be there.
-     *
-     * @param id the device identifier
-     */
-    void verifyGroups(DeviceId id);
-
-    /**
-     * Returns the internal link state as seen by this instance of the
-     * controller.
-     *
-     * @return the internal link state
-     */
-    ImmutableMap<Link, Boolean> getSeenLinks();
-
-    /**
-     * Returns the ports administratively disabled by the controller.
-     *
-     * @return a map of devices and port numbers for administratively disabled
-     *         ports. Does not include ports manually disabled by the operator.
-     */
-    ImmutableMap<DeviceId, Set<PortNumber>> getDownedPortState();
-
-    /**
-     * Returns the associated roles to the mcast groups.
-     *
-     * @param mcastIp the group ip
-     * @param sourcecp the source connect point
-     * @return the mapping mcastIp-device to mcast role
-     */
-    Map<McastRoleStoreKey, McastRole> getMcastRoles(IpAddress mcastIp,
-                                                    ConnectPoint sourcecp);
-
-    /**
-     * Returns the associated trees to the mcast group.
-     *
-     * @param mcastIp the group ip
-     * @param sourcecp the source connect point
-     * @return the mapping egress point to mcast path
-     */
-    Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
-                                                             ConnectPoint sourcecp);
-
-    /**
-     * Return the leaders of the mcast groups.
-     *
-     * @param mcastIp the group ip
-     * @return the mapping group-node
-     */
-    Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp);
-
-    /**
-     * Returns shouldProgram map.
-     *
-     * @return shouldProgram map
-     */
-    Map<Set<DeviceId>, NodeId> getShouldProgram();
-
-    /**
-     * Returns shouldProgram local cache.
-     *
-     * @return shouldProgram local cache
-     */
-    Map<DeviceId, Boolean> getShouldProgramCache();
-
-    /**
-     * Returns whether instance should program device or not.
-     *
-     * @param deviceId .
-     * @return boolean status saying instance should program device or not.
-     */
-    boolean shouldProgram(DeviceId deviceId);
-
-    /**
-     * Returns the mcast filtering obj.
-     *
-     * @return the mapping group-node
-     */
-    Map<DeviceId, List<McastFilteringObjStoreKey>> getMcastFilters();
-
-    /**
-     * Determines if routing in the network has been stable in the last
-     * STABILITY_THRESHOLD seconds, by comparing the current time to the last
-     * routing change timestamp.
-     *
-     * @return true if stable
-     */
-    boolean isRoutingStable();
-
-    /**
-     * Invoke hostHandler.init() for given device.
-     *
-     * @param deviceId device ID
-     */
-    void initHost(DeviceId deviceId);
-
-    /**
-     * Invoke routeHandler.init() for given device.
-     *
-     * @param deviceId device ID
-     */
-    void initRoute(DeviceId deviceId);
-
-    /**
-     * Gets application id.
-     *
-     * @return application id
-     */
-    default ApplicationId appId() {
-        throw new NotImplementedException("appId not implemented");
-    }
-
-    /**
-     * Returns internal VLAN for untagged hosts on given connect point.
-     * <p>
-     * The internal VLAN is either vlan-untagged for an access port,
-     * or vlan-native for a trunk port.
-     *
-     * @param connectPoint connect point
-     * @return internal VLAN or null if both vlan-untagged and vlan-native are undefined
-     */
-    default VlanId getInternalVlanId(ConnectPoint connectPoint) {
-        throw new NotImplementedException("getInternalVlanId not implemented");
-    }
-
-    /**
-     * Returns optional pair device ID of given device.
-     *
-     * @param deviceId device ID
-     * @return optional pair device ID. Might be empty if pair device is not configured
-     */
-    default Optional<DeviceId> getPairDeviceId(DeviceId deviceId) {
-        throw new NotImplementedException("getPairDeviceId not implemented");
-    }
-
-    /**
-     * Returns optional pair device local port of given device.
-     *
-     * @param deviceId device ID
-     * @return optional pair device ID. Might be empty if pair device is not configured
-     */
-    default Optional<PortNumber> getPairLocalPort(DeviceId deviceId) {
-        throw new NotImplementedException("getPairLocalPort not implemented");
-    }
-
-    /**
-     * Returns a set of infrastructure ports on the given device.
-     *
-     * @param deviceId device ID
-     * @return a set of ports that does not have interface configuration
-     */
-    default Set<PortNumber> getInfraPorts(DeviceId deviceId) {
-        throw new NotImplementedException("getInfraPorts not implemented");
-    }
-
-    /**
-     * Returns a set of edge ports on the given device.
-     *
-     * @param deviceId device ID
-     * @return a set of ports that has interface configuration
-     */
-    default Set<PortNumber> getEdgePorts(DeviceId deviceId) {
-        throw new NotImplementedException("getEdgePorts not implemented");
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TopologyHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TopologyHandler.java
deleted file mode 100644
index 72b1a70..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TopologyHandler.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2018-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.Maps;
-import org.onosproject.event.Event;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.link.LinkEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * Handler for topology events.
- */
-class TopologyHandler {
-
-    // Logging instance
-    private static final Logger log = LoggerFactory.getLogger(TopologyHandler.class);
-    // Internal reference for SR manager and its services
-    private final SegmentRoutingManager srManager;
-
-    /**
-     * Constructs the TopologyHandler.
-     *
-     * @param srManager Segment Routing manager
-     */
-    TopologyHandler(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-    }
-
-    // Check if the link event is valid
-    private boolean isValid(LinkEvent linkEvent) {
-        Link link = linkEvent.subject();
-        // Verify if the link is valid with the link handler
-        if (!srManager.linkHandler.isLinkValid(link)) {
-            log.debug("Link {} ignored by the LinkHandler", link);
-            return false;
-        }
-        // Processing for LINK_REMOVED
-        if (linkEvent.type() == LinkEvent.Type.LINK_REMOVED) {
-            // device availability check helps to ensure that multiple link-removed
-            // events are actually treated as a single switch removed event.
-            // purgeSeenLink is necessary so we do rerouting (instead of rehashing)
-            // when switch comes back.
-            if (link.src().elementId() instanceof DeviceId
-                    && !srManager.deviceService.isAvailable(link.src().deviceId())) {
-                log.debug("Link {} ignored device {} is down", link, link.src().deviceId());
-                return false;
-            }
-            if (link.dst().elementId() instanceof DeviceId
-                    && !srManager.deviceService.isAvailable(link.dst().deviceId())) {
-                log.debug("Link {} ignored device {} is down", link, link.dst().deviceId());
-                return false;
-            }
-            // LINK_REMOVED is ok
-            return true;
-        }
-        // Processing for LINK_ADDED and LINK_UPDATED
-        // Verify if source device is configured
-        if (srManager.deviceConfiguration == null ||
-                !srManager.deviceConfiguration.isConfigured(link.src().deviceId())) {
-            // Source device is not configured, not valid for us
-            log.warn("Source device of this link is not configured.. "
-                             + "not processing further");
-            return false;
-        }
-        // LINK_ADDED/LINK_UPDATED is ok
-        return true;
-    }
-
-    // Check if the device event is valid
-    private boolean isValid(DeviceEvent deviceEvent) {
-        Device device = deviceEvent.subject();
-        // We don't process the event if the device is available
-        return !srManager.deviceService.isAvailable(device.id());
-    }
-
-    /**
-     * Process the TOPOLOGY_CHANGE event. An initial optimization
-     * is performed to avoid the processing of not relevant events.
-     *
-     * @param reasons list of events that triggered topology change
-     */
-    void processTopologyChange(List<Event> reasons) {
-        // Store temporary in the map all the link events,
-        // events having the same subject will be automatically
-        // overridden.
-        Map<Link, LinkEvent> linkEvents = Maps.newHashMap();
-        // Store temporary in the map all the device events,
-        // events having the same subject will be automatically
-        // overridden.
-        Map<DeviceId, DeviceEvent> deviceEvents = Maps.newHashMap();
-        // Pre-process all the events putting them in the right map
-        reasons.forEach(reason -> {
-            // Relevant events for devices
-            if (reason.type() == DeviceEvent.Type.DEVICE_ADDED ||
-                    reason.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
-                    reason.type() == DeviceEvent.Type.DEVICE_UPDATED) {
-                // Take the event and save in the map
-                DeviceEvent deviceEvent = (DeviceEvent) reason;
-                deviceEvents.put(deviceEvent.subject().id(), deviceEvent);
-                /// Relevant events for links
-            } else if (reason.type() == LinkEvent.Type.LINK_ADDED ||
-                    reason.type() == LinkEvent.Type.LINK_UPDATED ||
-                    reason.type() == LinkEvent.Type.LINK_REMOVED) {
-                // Take the event and store the link in the map
-                LinkEvent linkEvent = (LinkEvent) reason;
-                linkEvents.put(linkEvent.subject(), linkEvent);
-                // Other events are not relevant
-            } else {
-                log.debug("Unhandled event type: {}", reason.type());
-            }
-        });
-        // Verify if the link events are valid
-        // before sent for mcast handling
-        List<LinkEvent> toProcessLinkEvent = linkEvents.values()
-                .stream()
-                .filter(this::isValid)
-                .collect(Collectors.toList());
-        // Verify if the device events are valid
-        // before sent for mcast handling
-        List<DeviceEvent> toProcessDeviceEvent = deviceEvents.values()
-                .stream()
-                .filter(this::isValid)
-                .collect(Collectors.toList());
-
-        // Processing part of the received events
-        // We don't need to process all LINK_ADDED
-        boolean isLinkAdded = false;
-        // Iterate on link events
-        for (LinkEvent linkEvent : toProcessLinkEvent) {
-            // We process just the first one
-            if (linkEvent.type() == LinkEvent.Type.LINK_ADDED ||
-                    linkEvent.type() == LinkEvent.Type.LINK_UPDATED) {
-                // Other ones are skipped
-                if (isLinkAdded) {
-                    continue;
-                }
-                log.info("Processing - Event: {}", linkEvent);
-                // First time, let's process it
-                isLinkAdded = true;
-                // McastHandler, reroute all the mcast tree
-                srManager.mcastHandler.init();
-            } else {
-                log.info("Processing - Event: {}", linkEvent);
-                // We compute each time a LINK_DOWN event
-                srManager.mcastHandler.processLinkDown(linkEvent.subject());
-            }
-        }
-        // Process all the device events
-        toProcessDeviceEvent.forEach(deviceEvent -> {
-            log.info("Processing - Event: {}", deviceEvent);
-            srManager.mcastHandler.processDeviceDown(deviceEvent.subject().id());
-        });
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Tunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Tunnel.java
deleted file mode 100644
index 470662f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Tunnel.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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 java.util.List;
-
-/**
- * Tunnel interface.
- */
-public interface Tunnel {
-
-    /**
-     * Returns the tunnel ID.
-     *
-     * @return tunnel ID
-     */
-    String id();
-
-    /**
-     * Returns Segment IDs for the tunnel including source and destination.
-     *
-     * @return List of Node ID
-     */
-    List<Integer> labelIds();
-
-    /**
-     * Returns the group ID for the tunnel.
-     *
-     * @return group ID
-     */
-    int groupId();
-
-    /**
-     * Sets group ID for the tunnel.
-     *
-     * @param groupId group identifier
-     */
-    void setGroupId(int groupId);
-
-    /**
-     * Sets the flag to allow to remove the group or not.
-     *
-     * @param ok the flag; true - allow to remove
-     */
-    void allowToRemoveGroup(boolean ok);
-
-    /**
-     * Checks if it is allowed to remove the group for the tunnel.
-     *
-     * @return true if allowed, false otherwise
-     */
-    boolean isAllowedToRemoveGroup();
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
deleted file mode 100644
index 7031507..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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 org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Tunnel Handler.
- */
-public class TunnelHandler {
-    protected final Logger log = getLogger(getClass());
-
-    private final DeviceConfiguration config;
-    private final EventuallyConsistentMap<String, Tunnel> tunnelStore;
-    private Map<DeviceId, DefaultGroupHandler> groupHandlerMap;
-    private LinkService linkService;
-
-    /**
-     * Result of tunnel creation or removal.
-     */
-    public enum Result {
-        /**
-         * Success.
-         */
-        SUCCESS,
-
-        /**
-         * More than one router needs to specified to created a tunnel.
-         */
-        WRONG_PATH,
-
-        /**
-         * The same tunnel exists already.
-         */
-        TUNNEL_EXISTS,
-
-        /**
-         * The same tunnel ID exists already.
-         */
-        ID_EXISTS,
-
-        /**
-         * Tunnel not found.
-         */
-        TUNNEL_NOT_FOUND,
-
-        /**
-         * Cannot remove the tunnel used by a policy.
-         */
-        TUNNEL_IN_USE,
-
-        /**
-         * Failed to create/remove groups for the tunnel.
-         */
-        INTERNAL_ERROR
-    }
-
-    /**
-     * Constructs tunnel handler.
-     *
-     * @param linkService link service
-     * @param deviceConfiguration device configuration
-     * @param groupHandlerMap group handler map
-     * @param tunnelStore tunnel store
-     */
-    public TunnelHandler(LinkService linkService,
-                         DeviceConfiguration deviceConfiguration,
-                         Map<DeviceId, DefaultGroupHandler> groupHandlerMap,
-                         EventuallyConsistentMap<String, Tunnel> tunnelStore) {
-        this.linkService = linkService;
-        this.config = deviceConfiguration;
-        this.groupHandlerMap = groupHandlerMap;
-        this.tunnelStore = tunnelStore;
-    }
-
-    /**
-     * Creates a tunnel.
-     *
-     * @param tunnel tunnel reference to create a tunnel
-     * @return WRONG_PATH if the tunnel path is wrong, ID_EXISTS if the tunnel ID
-     * exists already, TUNNEL_EXISTS if the same tunnel exists, INTERNAL_ERROR
-     * if the tunnel creation failed internally, SUCCESS if the tunnel is created
-     * successfully
-     */
-    public Result createTunnel(Tunnel tunnel) {
-
-        if (tunnel.labelIds().isEmpty() || tunnel.labelIds().size() < 3) {
-            log.error("More than one router needs to specified to created a tunnel");
-            return Result.WRONG_PATH;
-        }
-
-        if (tunnelStore.containsKey(tunnel.id())) {
-            log.warn("The same tunnel ID exists already");
-            return Result.ID_EXISTS;
-        }
-
-        if (tunnelStore.containsValue(tunnel)) {
-            log.warn("The same tunnel exists already");
-            return Result.TUNNEL_EXISTS;
-        }
-
-        int groupId = createGroupsForTunnel(tunnel);
-        if (groupId < 0) {
-            log.error("Failed to create groups for the tunnel");
-            return Result.INTERNAL_ERROR;
-        }
-
-        tunnel.setGroupId(groupId);
-        tunnelStore.put(tunnel.id(), tunnel);
-
-        return Result.SUCCESS;
-    }
-
-    /**
-     * Removes the tunnel with the tunnel ID given.
-     *
-     * @param tunnelInfo tunnel information to delete tunnels
-     * @return TUNNEL_NOT_FOUND if the tunnel to remove does not exists,
-     * INTERNAL_ERROR if the tunnel creation failed internally, SUCCESS
-     * if the tunnel is created successfully.
-     */
-    public Result removeTunnel(Tunnel tunnelInfo) {
-
-        Tunnel tunnel = tunnelStore.get(tunnelInfo.id());
-        if (tunnel != null) {
-            DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
-            if (tunnel.isAllowedToRemoveGroup()) {
-                if (groupHandlerMap.get(deviceId).removeGroup(tunnel.groupId())) {
-                    tunnelStore.remove(tunnel.id());
-                } else {
-                    log.error("Failed to remove the tunnel {}", tunnelInfo.id());
-                    return Result.INTERNAL_ERROR;
-                }
-            } else {
-                log.debug("The group is not removed because it is being used.");
-                tunnelStore.remove(tunnel.id());
-            }
-        } else {
-            log.error("No tunnel found for tunnel ID {}", tunnelInfo.id());
-            return Result.TUNNEL_NOT_FOUND;
-        }
-
-        return Result.SUCCESS;
-    }
-
-    /**
-     * Returns the tunnel with the tunnel ID given.
-     *
-     * @param tid Tunnel ID
-     * @return Tunnel reference
-     */
-    public Tunnel getTunnel(String tid) {
-        return tunnelStore.get(tid);
-    }
-
-    /**
-     * Returns all tunnels.
-     *
-     * @return list of Tunnels
-     */
-    public List<Tunnel> getTunnels() {
-        List<Tunnel> tunnels = new ArrayList<>();
-        tunnelStore.values().forEach(tunnel -> tunnels.add(
-                new DefaultTunnel((DefaultTunnel) tunnel)));
-
-        return tunnels;
-    }
-
-    private int createGroupsForTunnel(Tunnel tunnel) {
-
-        Set<Integer> portNumbers;
-        final int groupError = -1;
-
-        DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
-        if (deviceId == null) {
-            log.warn("No device found for SID {}", tunnel.labelIds().get(0));
-            return groupError;
-        } else if (groupHandlerMap.get(deviceId) == null) {
-            log.warn("group handler not found for {}", deviceId);
-            return groupError;
-        }
-        Set<DeviceId> deviceIds = new HashSet<>();
-        int sid = tunnel.labelIds().get(1);
-        if (config.isAdjacencySid(deviceId, sid)) {
-            portNumbers = config.getPortsForAdjacencySid(deviceId, sid);
-            for (Link link: linkService.getDeviceEgressLinks(deviceId)) {
-                for (Integer port: portNumbers) {
-                    if (link.src().port().toLong() == port) {
-                        deviceIds.add(link.dst().deviceId());
-                    }
-                }
-            }
-        } else {
-            deviceIds.add(config.getDeviceId(sid));
-        }
-        // For these NeighborSet isMpls is meaningless.
-        // TODO : Revisit this, the code and also the type
-        DestinationSet ns = DestinationSet.createTypePushBos(
-                                               tunnel.labelIds().get(2),
-                                               DeviceId.NONE);
-
-        // If the tunnel reuses any existing groups, then tunnel handler
-        // should not remove the group.
-        if (groupHandlerMap.get(deviceId).hasNextObjectiveId(ns)) {
-            tunnel.allowToRemoveGroup(false);
-        } else {
-            tunnel.allowToRemoveGroup(true);
-        }
-
-        return groupHandlerMap.get(deviceId).getNextObjectiveId(ns, null, null, true);
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
deleted file mode 100644
index 5df82af..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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 java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Tunnel Policy.
- */
-public final class TunnelPolicy implements Policy {
-
-    private final Type type;
-    private final String id;
-    private final int priority;
-    private final String tunnelId;
-    private String dstIp;
-    private String srcIp;
-    private String ipProto;
-    private short srcPort;
-    private short dstPort;
-
-    private TunnelPolicy(String policyId, Type type, int priority, String tunnelId, String srcIp,
-                         String dstIp, String ipProto, short srcPort, short dstPort) {
-        this.id = checkNotNull(policyId);
-        this.type = type;
-        this.tunnelId = tunnelId;
-        this.priority = priority;
-        this.dstIp = dstIp;
-        this.srcIp = srcIp;
-        this.ipProto = ipProto;
-        this.srcPort = srcPort;
-        this.dstPort = dstPort;
-
-    }
-
-    /**
-     * Creates a TunnelPolicy reference.
-     *
-     * @param p TunnelPolicy reference
-     */
-    public TunnelPolicy(TunnelPolicy p) {
-        this.id = p.id;
-        this.type = p.type;
-        this.tunnelId = p.tunnelId;
-        this.priority = p.priority;
-        this.srcIp = p.srcIp;
-        this.dstIp = p.dstIp;
-        this.ipProto = p.ipProto;
-        this.srcPort = p.srcPort;
-        this.dstPort = p.dstPort;
-    }
-
-    /**
-     * Returns the TunnelPolicy builder reference.
-     *
-     * @return TunnelPolicy builder
-     */
-    public static TunnelPolicy.Builder builder() {
-        return new Builder();
-    }
-
-    @Override
-    public String id() {
-        return this.id;
-    }
-
-    @Override
-    public int priority() {
-        return priority;
-    }
-
-    @Override
-    public Type type() {
-        return type;
-    }
-
-    @Override
-    public String srcIp() {
-        return srcIp;
-    }
-
-    @Override
-    public String dstIp() {
-        return dstIp;
-    }
-
-    @Override
-    public String ipProto() {
-        return ipProto;
-    }
-
-    @Override
-    public short srcPort() {
-        return srcPort;
-    }
-
-    @Override
-    public short dstPort() {
-        return dstPort;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (o instanceof TunnelPolicy) {
-            TunnelPolicy that = (TunnelPolicy) o;
-            // We do not compare the policy ID
-            if (this.type.equals(that.type) &&
-                    this.tunnelId.equals(that.tunnelId) &&
-                    this.priority == that.priority &&
-                    this.srcIp.equals(that.srcIp) &&
-                    this.dstIp.equals(that.dstIp) &&
-                    this.srcPort == that.srcPort &&
-                    this.dstPort == that.dstPort &&
-                    this.ipProto.equals(that.ipProto)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(type, tunnelId, srcIp, dstIp, ipProto,
-                srcPort, dstPort, priority);
-    }
-
-    /**
-     * Returns the tunnel ID of the policy.
-     *
-     * @return Tunnel ID
-     */
-    public String tunnelId() {
-        return this.tunnelId;
-    }
-
-
-    /**
-     * Tunnel Policy Builder.
-     */
-    public static final class Builder {
-
-        private String id;
-        private Type type;
-        private int priority;
-        private String tunnelId;
-        private String dstIp;
-        private String srcIp;
-        private String ipProto;
-        private short srcPort;
-        private short dstPort;
-
-        /**
-         * Sets the policy Id.
-         *
-         * @param id policy Id
-         * @return Builder object
-         */
-        public Builder setPolicyId(String id) {
-            this.id = id;
-
-            return this;
-        }
-
-        /**
-         * Sets the policy type.
-         *
-         * @param type policy type
-         * @return Builder object
-         */
-        public Builder setType(Type type) {
-            this.type = type;
-
-            return this;
-        }
-
-        /**
-         * Sets the source IP address.
-         *
-         * @param srcIp source IP address
-         * @return Builder object
-         */
-        public Builder setSrcIp(String srcIp) {
-            this.srcIp = srcIp;
-
-            return this;
-        }
-
-        /**
-         * Sets the destination IP address.
-         *
-         * @param dstIp destination IP address
-         * @return Builder object
-         */
-        public Builder setDstIp(String dstIp) {
-            this.dstIp = dstIp;
-
-            return this;
-        }
-
-        /**
-         * Sets the IP protocol.
-         *
-         * @param proto IP protocol
-         * @return Builder object
-         */
-        public Builder setIpProto(String proto) {
-            this.ipProto = proto;
-
-            return this;
-        }
-
-        /**
-         * Sets the source port.
-         *
-         * @param srcPort source port
-         * @return Builder object
-         */
-        public Builder setSrcPort(short srcPort) {
-            this.srcPort = srcPort;
-
-            return this;
-        }
-
-        /**
-         * Sets the destination port.
-         *
-         * @param dstPort destination port
-         * @return Builder object
-         */
-        public Builder setDstPort(short dstPort) {
-            this.dstPort = dstPort;
-
-            return this;
-        }
-
-        /**
-         * Sets the priority of the policy.
-         *
-         * @param p priority
-         * @return Builder object
-         */
-        public Builder setPriority(int p) {
-            this.priority = p;
-
-            return this;
-        }
-
-        /**
-         * Sets the tunnel Id.
-         *
-         * @param tunnelId tunnel Id
-         * @return Builder object
-         */
-        public Builder setTunnelId(String tunnelId) {
-            this.tunnelId = tunnelId;
-
-            return this;
-        }
-
-        /**
-         * Builds the policy.
-         *
-         * @return Tunnel Policy reference
-         */
-        public Policy build() {
-            return new TunnelPolicy(id, type, priority, tunnelId, srcIp, dstIp,
-                    ipProto, srcPort, dstPort);
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/BlackHoleCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/BlackHoleCommand.java
deleted file mode 100644
index c45ff8e..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/BlackHoleCommand.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Sets;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-
-import java.util.Set;
-
-/**
- * CLI command for managing black hole routes.
- */
-@Service
-@Command(scope = "onos", name = "sr-blackhole",
-        description = "Manage black hole routes")
-public class BlackHoleCommand extends AbstractShellCommand {
-    @Argument(index = 0, name = "op",
-            description = "list, add or remove",
-            required = true, multiValued = false)
-    private String op;
-
-    @Argument(index = 1, name = "prefix",
-            description = "IP prefix",
-            required = false, multiValued = false)
-    private String prefix;
-
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService = AbstractShellCommand.get(SegmentRoutingService.class);
-        NetworkConfigService netcfgService = AbstractShellCommand.get(NetworkConfigService.class);
-
-        SegmentRoutingAppConfig appConfig = netcfgService.getConfig(srService.appId(), SegmentRoutingAppConfig.class);
-        if (appConfig == null) {
-            JsonNode jsonNode = new ObjectMapper().createObjectNode();
-            netcfgService.applyConfig(srService.appId(), SegmentRoutingAppConfig.class, jsonNode);
-            appConfig = netcfgService.getConfig(srService.appId(), SegmentRoutingAppConfig.class);
-        }
-
-        Set<IpPrefix> blackHoleIps;
-        switch (op) {
-            case "list":
-                appConfig.blackholeIPs().forEach(prefix -> print(prefix.toString()));
-                break;
-            case "add":
-                blackHoleIps = Sets.newConcurrentHashSet(appConfig.blackholeIPs());
-                blackHoleIps.add(IpPrefix.valueOf(prefix));
-                appConfig.setBalckholeIps(blackHoleIps);
-                break;
-            case "remove":
-                blackHoleIps = Sets.newConcurrentHashSet(appConfig.blackholeIPs());
-                blackHoleIps.remove(IpPrefix.valueOf(prefix));
-                appConfig.setBalckholeIps(blackHoleIps);
-                break;
-            default:
-                throw new UnsupportedOperationException("Unknown operation " + op);
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java
deleted file mode 100644
index 8f706b0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2016-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Command to list device-subnet mapping in Segment Routing.
- */
-@Service
-@Command(scope = "onos", name = "sr-device-subnets",
-        description = "List device-subnet mapping in Segment Routing")
-public class DeviceSubnetListCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        printDeviceSubnetMap(srService.getDeviceSubnetMap());
-    }
-
-    private void printDeviceSubnetMap(Map<DeviceId, Set<IpPrefix>> deviceSubnetMap) {
-        deviceSubnetMap.forEach(((deviceId, ipPrefices) -> {
-            print("%s", deviceId);
-            ipPrefices.forEach(ipPrefix -> print("    %s", ipPrefix));
-        }));
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/EcmpGraphCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/EcmpGraphCommand.java
deleted file mode 100644
index 269134d..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/EcmpGraphCommand.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016-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.cli;
-
-
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.EcmpShortestPathGraph;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Command to read the current state of the ECMP shortest-path graph.
- *
- */
-@Service
-@Command(scope = "onos", name = "sr-ecmp-spg",
-        description = "Displays the current ecmp shortest-path-graph in this "
-                + "controller instance")
-public class EcmpGraphCommand extends AbstractShellCommand {
-
-    private static final String FORMAT_MAPPING = "  %s";
-
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        printEcmpGraph(srService.getCurrentEcmpSpg());
-    }
-
-    private void printEcmpGraph(Map<DeviceId, EcmpShortestPathGraph> currentEcmpSpg) {
-        if (currentEcmpSpg == null) {
-            print(FORMAT_MAPPING, "No ECMP graph found");
-            return;
-        }
-        StringBuilder ecmp = new StringBuilder();
-        currentEcmpSpg.forEach((key, value) -> {
-            ecmp.append("\n\nRoot Device: " + key + " ECMP Paths: " + value);
-        });
-        print(FORMAT_MAPPING, ecmp.toString());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/InvalidateNextCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/InvalidateNextCommand.java
deleted file mode 100644
index 094bea9..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/InvalidateNextCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.osgi.ServiceNotFoundException;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Command to invalidate next id from SR internal stores.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-invalidate",
-        description = "Invalidate given next id from SR internal stores")
-public class InvalidateNextCommand extends AbstractShellCommand {
-
-    private static final String CONFIRM_PHRASE = "please";
-
-    @Argument(name = "nextId", description = "Next ID", index = 0)
-    private String nextId = null;
-
-    @Argument(name = "confirm", description = "Confirmation phrase", index = 1)
-    private String please = null;
-
-    @Override
-    protected void doExecute() {
-        if (please == null || !please.equals(CONFIRM_PHRASE)) {
-            print("WARNING: System may enter an unpredictable state if the next ID is force invalidated." +
-                    "Enter confirmation phrase to continue.");
-            return;
-        }
-
-        try {
-            SegmentRoutingService srService = AbstractShellCommand.get(SegmentRoutingService.class);
-            srService.invalidateNextObj(Integer.parseInt(nextId));
-        } catch (ServiceNotFoundException e) {
-            print("SegmentRoutingService unavailable");
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/LinkStateCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/LinkStateCommand.java
deleted file mode 100644
index 9d7147b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/LinkStateCommand.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-
-/**
- * Command to read the current state of the DestinationSetNextObjectiveStore.
- *
- */
-@Service
-@Command(scope = "onos", name = "sr-link-state", description = "Displays the current internal link state "
-        + "noted by this instance of the controller")
-public class LinkStateCommand extends AbstractShellCommand {
-    private static final String FORMAT_MAPPING = "  %s";
-
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService = AbstractShellCommand
-                .get(SegmentRoutingService.class);
-        printLinkState(srService.getSeenLinks(),
-                       srService.getDownedPortState());
-    }
-
-    private void printLinkState(ImmutableMap<Link, Boolean> seenLinks,
-                                ImmutableMap<DeviceId, Set<PortNumber>> downedPortState) {
-        List<Link> a = Lists.newArrayList();
-        a.addAll(seenLinks.keySet());
-        a.sort(new CompLinks());
-
-        StringBuilder slbldr = new StringBuilder();
-        slbldr.append("\n Seen Links: ");
-        for (int i = 0; i < a.size(); i++) {
-            slbldr.append("\n "
-                    + (seenLinks.get(a.get(i)) == Boolean.TRUE ? "  up : "
-                                                               : "down : "));
-            slbldr.append(a.get(i).src() + " --> " + a.get(i).dst());
-        }
-        print(FORMAT_MAPPING, slbldr.toString());
-
-        StringBuilder dpbldr = new StringBuilder();
-        dpbldr.append("\n\n Administratively Disabled Ports: ");
-        downedPortState.entrySet().forEach(entry -> dpbldr
-                .append("\n " + entry.getKey() + entry.getValue()));
-        print(FORMAT_MAPPING, dpbldr.toString());
-    }
-
-    static class CompLinks implements Comparator<Link> {
-
-        @Override
-        public int compare(Link o1, Link o2) {
-            int res = o1.src().deviceId().toString()
-                    .compareTo(o2.src().deviceId().toString());
-            if (res < 0) {
-                return -1;
-            } else if (res > 0) {
-                return +1;
-            }
-            if (o1.src().port().toLong() < o2.src().port().toLong()) {
-                return -1;
-            }
-            return +1;
-        }
-
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastFilterListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastFilterListCommand.java
deleted file mode 100644
index bc1eb42..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastFilterListCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.mcast.McastFilteringObjStoreKey;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Command to show the list of mcast filtering obj.
- */
-@Service
-@Command(scope = "onos", name = "sr-filt-mcast",
-        description = "Lists all mcast filtering objs")
-public class McastFilterListCommand extends AbstractShellCommand {
-
-    private static final String FORMAT_HEADER = "device=%s";
-    private static final String FILTER_HEADER = "\t%s,%s,%s";
-
-    @Override
-    protected void doExecute() {
-        // Get SR service
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        // Get the filt objs
-        Map<DeviceId, List<McastFilteringObjStoreKey>> filteringObjKeys = srService.getMcastFilters();
-        filteringObjKeys.forEach(this::printMcastFilter);
-    }
-
-    private void printMcastFilter(DeviceId deviceId, List<McastFilteringObjStoreKey> filteringObjs) {
-        print(FORMAT_HEADER, deviceId);
-        filteringObjs.forEach(filteringObj -> print(FILTER_HEADER, filteringObj.ingressCP(),
-                                                    filteringObj.isIpv4() ? "IPv4" : "IPv6",
-                                                    filteringObj.vlanId()));
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastLeaderListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastLeaderListCommand.java
deleted file mode 100644
index 633745c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastLeaderListCommand.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.Map;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the mcast leaders of the groups.
- */
-@Service
-@Command(scope = "onos", name = "sr-mcast-leader",
-        description = "Lists all mcast leaders")
-public class McastLeaderListCommand extends AbstractShellCommand {
-
-    // OSGi workaround to introduce package dependency
-    McastGroupCompleter completer;
-
-    // Format for group line
-    private static final String G_FORMAT_MAPPING = "group=%s, leader=%s";
-
-    @Option(name = "-gAddr", aliases = "--groupAddress",
-            description = "IP Address of the multicast group",
-            valueToShowInHelp = "224.0.0.0",
-            required = false, multiValued = false)
-    @Completion(McastGroupCompleter.class)
-    String gAddr = null;
-
-    @Override
-    protected void doExecute() {
-        // Verify mcast group
-        IpAddress mcastGroup = null;
-        if (!isNullOrEmpty(gAddr)) {
-            mcastGroup = IpAddress.valueOf(gAddr);
-        }
-        // Get SR service
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        // Get the mapping
-        Map<IpAddress, NodeId> keyToRole = srService.getMcastLeaders(mcastGroup);
-        // And print local cache
-        keyToRole.forEach(this::printMcastLeder);
-    }
-
-    private void printMcastLeder(IpAddress mcastGroup,
-                                 NodeId nodeId) {
-        print(G_FORMAT_MAPPING, mcastGroup, nodeId);
-    }
-
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java
deleted file mode 100644
index 7dd6fd3..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import com.google.common.collect.Maps;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.mcast.McastStoreKey;
-import org.apache.commons.lang3.tuple.Pair;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the list of mcast nextids.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-mcast",
-        description = "Lists all mcast nextids")
-public class McastNextListCommand extends AbstractShellCommand {
-
-    // OSGi workaround to introduce package dependency
-    McastGroupCompleter completer;
-
-    // Format for group line
-    private static final String FORMAT_MAPPING = "group=%s, deviceIds-nextIds=%s";
-
-    @Option(name = "-gAddr", aliases = "--groupAddress",
-            description = "IP Address of the multicast group",
-            valueToShowInHelp = "224.0.0.0",
-            required = false, multiValued = false)
-    @Completion(McastGroupCompleter.class)
-    String gAddr = null;
-
-    @Override
-    protected void doExecute() {
-        // Verify mcast group
-        IpAddress mcastGroup = null;
-        if (!isNullOrEmpty(gAddr)) {
-            mcastGroup = IpAddress.valueOf(gAddr);
-        }
-        // Get SR service
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        // Get the mapping
-        Map<McastStoreKey, Integer> keyToNextId = srService.getMcastNextIds(mcastGroup);
-        // Reduce to the set of mcast groups
-        Set<IpAddress> mcastGroups = keyToNextId.keySet().stream()
-                .map(McastStoreKey::mcastIp)
-                .collect(Collectors.toSet());
-        // Print the nextids for each group
-        mcastGroups.forEach(group -> {
-            // Create a new map for the group
-            Map<Pair<DeviceId, VlanId>, Integer> deviceIdNextMap = Maps.newHashMap();
-            keyToNextId.entrySet()
-                    .stream()
-                    // Filter only the elements related to this group
-                    .filter(entry -> entry.getKey().mcastIp().equals(group))
-                    // For each create a new entry in the group related map
-                    .forEach(entry -> deviceIdNextMap.put(Pair.of(entry.getKey().deviceId(),
-                                                          entry.getKey().vlanId()), entry.getValue()));
-            // Print the map
-            printMcastNext(group, deviceIdNextMap);
-        });
-    }
-
-    private void printMcastNext(IpAddress mcastGroup, Map<Pair<DeviceId, VlanId>, Integer> deviceIdNextMap) {
-        print(FORMAT_MAPPING, mcastGroup, deviceIdNextMap);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastRoleListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastRoleListCommand.java
deleted file mode 100644
index 2b22c67..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastRoleListCommand.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.ConnectPointCompleter;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.mcast.McastRole;
-import org.onosproject.segmentrouting.mcast.McastRoleStoreKey;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the list of mcast roles.
- */
-@Service
-@Command(scope = "onos", name = "sr-mcast-role",
-        description = "Lists all mcast roles")
-public class McastRoleListCommand extends AbstractShellCommand {
-
-    // OSGi workaround to introduce package dependency
-    McastGroupCompleter completer;
-
-    // Format for group line
-    private static final String FORMAT_MAPPING = "%s,%s  ingress=%s\ttransit=%s\tegress=%s";
-
-    @Option(name = "-gAddr", aliases = "--groupAddress",
-            description = "IP Address of the multicast group",
-            valueToShowInHelp = "224.0.0.0",
-            required = false, multiValued = false)
-    @Completion(McastGroupCompleter.class)
-    String gAddr = null;
-
-    @Option(name = "-src", aliases = "--connectPoint",
-            description = "Source port of:XXXXXXXXXX/XX",
-            valueToShowInHelp = "of:0000000000000001/1",
-            required = false, multiValued = false)
-    @Completion(ConnectPointCompleter.class)
-    String source = null;
-
-    @Override
-    protected void doExecute() {
-        // Verify mcast group
-        IpAddress mcastGroup = null;
-        // We want to use source cp only for a specific group
-        ConnectPoint sourcecp = null;
-        if (!isNullOrEmpty(gAddr)) {
-            mcastGroup = IpAddress.valueOf(gAddr);
-            if (!isNullOrEmpty(source)) {
-                sourcecp = ConnectPoint.deviceConnectPoint(source);
-            }
-        }
-        // Get SR service, the roles and the groups
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Map<McastRoleStoreKey, McastRole> keyToRole = srService.getMcastRoles(mcastGroup, sourcecp);
-        Set<IpAddress> mcastGroups = keyToRole.keySet().stream()
-                .map(McastRoleStoreKey::mcastIp)
-                .collect(Collectors.toSet());
-        // Print the trees for each group
-        mcastGroups.forEach(group -> {
-            // Create a new map for the group
-            Map<ConnectPoint, Multimap<McastRole, DeviceId>> roleDeviceIdMap = Maps.newHashMap();
-            keyToRole.entrySet()
-                    .stream()
-                    .filter(entry -> entry.getKey().mcastIp().equals(group))
-                    .forEach(entry -> roleDeviceIdMap.compute(entry.getKey().source(), (gsource, map) -> {
-                        map = map == null ? ArrayListMultimap.create() : map;
-                        map.put(entry.getValue(), entry.getKey().deviceId());
-                        return map;
-                    }));
-            roleDeviceIdMap.forEach((gsource, map) -> {
-                // Print the map
-                printMcastRole(group, gsource,
-                               map.get(McastRole.INGRESS),
-                               map.get(McastRole.TRANSIT),
-                               map.get(McastRole.EGRESS));
-            });
-        });
-    }
-
-    private void printMcastRole(IpAddress mcastGroup, ConnectPoint source,
-                                Collection<DeviceId> ingress,
-                                Collection<DeviceId> transit,
-                                Collection<DeviceId> egress) {
-        print(FORMAT_MAPPING, mcastGroup, source, ingress, transit, egress);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java
deleted file mode 100644
index 09c795c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.ConnectPointCompleter;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the list of mcast trees.
- */
-@Service
-@Command(scope = "onos", name = "sr-mcast-tree",
-        description = "Lists all mcast trees")
-public class McastTreeListCommand extends AbstractShellCommand {
-
-    // OSGi workaround to introduce package dependency
-    McastGroupCompleter completer;
-
-    // Format for group line
-    private static final String G_FORMAT_MAPPING = "group=%s";
-    // Format for sink line
-    private static final String S_FORMAT_MAPPING = "  sink=%s\tpath=%s";
-
-    @Option(name = "-gAddr", aliases = "--groupAddress",
-            description = "IP Address of the multicast group",
-            valueToShowInHelp = "224.0.0.0",
-            required = false, multiValued = false)
-    @Completion(McastGroupCompleter.class)
-    String gAddr = null;
-
-    @Option(name = "-src", aliases = "--connectPoint",
-            description = "Source port of:XXXXXXXXXX/XX",
-            valueToShowInHelp = "of:0000000000000001/1",
-            required = false, multiValued = false)
-    @Completion(ConnectPointCompleter.class)
-    String source = null;
-
-    @Override
-    protected void doExecute() {
-        // Get SR service and the handled mcast groups
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Set<IpAddress> mcastGroups = ImmutableSet.copyOf(srService.getMcastLeaders(null)
-                                                                         .keySet());
-
-        if (!isNullOrEmpty(gAddr)) {
-            mcastGroups = mcastGroups.stream()
-                    .filter(mcastIp -> mcastIp.equals(IpAddress.valueOf(gAddr)))
-                    .collect(Collectors.toSet());
-        }
-
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode root = mapper.createObjectNode();
-
-        // Print the trees for each group or build json objects
-        mcastGroups.forEach(group -> {
-            // We want to use source cp only for a specific group
-            ConnectPoint sourcecp = null;
-            if (!isNullOrEmpty(source) &&
-                    !isNullOrEmpty(gAddr)) {
-                sourcecp = ConnectPoint.deviceConnectPoint(source);
-            }
-            Multimap<ConnectPoint, List<ConnectPoint>> mcastTree = srService.getMcastTrees(group,
-                                                                                           sourcecp);
-            if (!mcastTree.isEmpty()) {
-                // Build a json object for each group
-                if (outputJson()) {
-                    root.putPOJO(group.toString(), json(mcastTree));
-                } else {
-                    // Banner and then the trees
-                    printMcastGroup(group);
-                    mcastTree.forEach(this::printMcastSink);
-                }
-            }
-        });
-
-        // Print the json object at the end
-        if (outputJson()) {
-            print("%s", root);
-        }
-
-    }
-
-    private void printMcastGroup(IpAddress mcastGroup) {
-        print(G_FORMAT_MAPPING, mcastGroup);
-    }
-
-    private void printMcastSink(ConnectPoint sink, List<ConnectPoint> path) {
-        print(S_FORMAT_MAPPING, sink, path);
-    }
-
-    private ObjectNode json(Multimap<ConnectPoint, List<ConnectPoint>> mcastTree) {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode jsonSinks = mapper.createObjectNode();
-        mcastTree.asMap().forEach((sink, paths) -> {
-            ArrayNode jsonPaths = mapper.createArrayNode();
-            paths.forEach(path -> {
-                ArrayNode jsonPath = mapper.createArrayNode();
-                path.forEach(connectPoint -> jsonPath.add(connectPoint.toString()));
-                jsonPaths.addPOJO(jsonPath);
-            });
-            jsonSinks.putPOJO(sink.toString(), jsonPaths);
-        });
-        return jsonSinks;
-    }
-
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextDstCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextDstCommand.java
deleted file mode 100644
index e6da695..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextDstCommand.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2016-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.cli;
-
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-
-/**
- * Command to read the current state of the DestinationSetNextObjectiveStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-dst",
-        description = "Displays the current next-hops seen by each switch "
-                + "towards a set of destinations and the next-id it maps to")
-public class NextDstCommand extends AbstractShellCommand {
-
-    private static final String FORMAT_MAPPING = "  %s";
-
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        printDestinationSet(srService.getDstNextObjStore());
-    }
-
-    private void printDestinationSet(Map<DestinationSetNextObjectiveStoreKey,
-                                      NextNeighbors> ds) {
-        ArrayList<DestinationSetNextObjectiveStoreKey> a = new ArrayList<>();
-        ds.keySet().forEach(key -> a.add(key));
-        a.sort(new Comp());
-
-        StringBuilder dsbldr = new StringBuilder();
-        for (int i = 0; i < a.size(); i++) {
-            dsbldr.append("\n " + a.get(i));
-            dsbldr.append(" --> via: " + ds.get(a.get(i)));
-        }
-        print(FORMAT_MAPPING, dsbldr.toString());
-    }
-
-    static class Comp implements Comparator<DestinationSetNextObjectiveStoreKey> {
-
-        @Override
-        public int compare(DestinationSetNextObjectiveStoreKey o1,
-                           DestinationSetNextObjectiveStoreKey o2) {
-            int res = o1.deviceId().toString().compareTo(o2.deviceId().toString());
-            if (res < 0) {
-                return -1;
-            } else if (res > 0) {
-                return +1;
-            }
-            return 0;
-        }
-
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextMacVlanCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextMacVlanCommand.java
deleted file mode 100644
index e31e693..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextMacVlanCommand.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the macVlanNextObjStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-mac-vlan",
-        description = "Displays the current next-hop / next-id it mapping")
-public class NextMacVlanCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        print(srService.getMacVlanNextObjStore());
-    }
-
-    private void print(Map<MacVlanNextObjectiveStoreKey, Integer> macVlanNextObjStore) {
-        ArrayList<MacVlanNextObjectiveStoreKey> a = new ArrayList<>(macVlanNextObjStore.keySet());
-        a.sort(Comparator
-                .comparing((MacVlanNextObjectiveStoreKey o) -> o.deviceId().toString())
-                .thenComparing((MacVlanNextObjectiveStoreKey o) -> o.vlanId().toString())
-                .thenComparing((MacVlanNextObjectiveStoreKey o) -> o.macAddr().toString()));
-
-        StringBuilder builder = new StringBuilder();
-        a.forEach(k ->
-            builder.append("\n")
-                    .append(k)
-                    .append(" --> ")
-                    .append(macVlanNextObjStore.get(k))
-        );
-        print(builder.toString());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextPortCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextPortCommand.java
deleted file mode 100644
index fddc1d7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextPortCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the portNextObjStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-port",
-        description = "Displays the current port / next-id it mapping")
-public class NextPortCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        print(srService.getPortNextObjStore());
-    }
-
-    private void print(Map<PortNextObjectiveStoreKey, Integer> portNextObjStore) {
-        ArrayList<PortNextObjectiveStoreKey> a = new ArrayList<>(portNextObjStore.keySet());
-        a.sort(Comparator
-                .comparing((PortNextObjectiveStoreKey o) -> o.deviceId().toString())
-                .thenComparing((PortNextObjectiveStoreKey o) -> o.portNumber().toLong()));
-
-        StringBuilder builder = new StringBuilder();
-        a.forEach(k ->
-            builder.append("\n")
-                    .append(k)
-                    .append(" --> ")
-                    .append(portNextObjStore.get(k))
-        );
-        print(builder.toString());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextVlanCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextVlanCommand.java
deleted file mode 100644
index 8518a5f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextVlanCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the vlanNextObjStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-vlan",
-        description = "Displays the current vlan / next-id it mapping")
-public class NextVlanCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        print(srService.getVlanNextObjStore());
-    }
-
-    private void print(Map<VlanNextObjectiveStoreKey, Integer> vlanNextObjStore) {
-        ArrayList<VlanNextObjectiveStoreKey> a = new ArrayList<>(vlanNextObjStore.keySet());
-        a.sort(Comparator
-                .comparing((VlanNextObjectiveStoreKey o) -> o.deviceId().toString())
-                .thenComparing((VlanNextObjectiveStoreKey o) -> o.vlanId().toShort()));
-
-        StringBuilder builder = new StringBuilder();
-        a.forEach(k ->
-            builder.append("\n")
-                    .append(k)
-                    .append(" --> ")
-                    .append(vlanNextObjStore.get(k))
-        );
-        print(builder.toString());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhaseCompleter.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhaseCompleter.java
deleted file mode 100644
index bd16068..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhaseCompleter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2014-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.cli;
-
-import com.google.common.collect.Lists;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractChoicesCompleter;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Phase completer.
- */
-@Service
-public class PhaseCompleter extends AbstractChoicesCompleter {
-    @Override
-    protected List<String> choices() {
-        return Lists.newArrayList(Phase.values()).stream().map(Enum::toString).collect(Collectors.toList());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoveryListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoveryListCommand.java
deleted file mode 100644
index 6efdaaa..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoveryListCommand.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-
-@Service
-@Command(scope = "onos", name = "sr-pr-list", description = "List current recovery phase of each device")
-
-public class PhasedRecoveryListCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        PhasedRecoveryService prService = get(PhasedRecoveryService.class);
-        print(prService.getPhases().toString());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoverySetCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoverySetCommand.java
deleted file mode 100644
index 50e3bc6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoverySetCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-
-@Service
-@Command(scope = "onos", name = "sr-pr-set", description = "Set recovery phase of given device")
-
-public class PhasedRecoverySetCommand extends AbstractShellCommand {
-    @Argument(index = 0, name = "deviceId",
-            description = "Device ID",
-            required = true, multiValued = false)
-    @Completion(DeviceIdCompleter.class)
-    private String deviceIdStr;
-
-    @Argument(index = 1, name = "phase",
-            description = "Recovery phase",
-            required = true, multiValued = false)
-    @Completion(PhaseCompleter.class)
-    private String phaseStr;
-
-    @Override
-    protected void doExecute() {
-        DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
-        Phase newPhase = Phase.valueOf(phaseStr);
-
-        PhasedRecoveryService prService = get(PhasedRecoveryService.class);
-        prService.setPhase(deviceId, newPhase);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyAddCommand.java
deleted file mode 100644
index 1f75317..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyAddCommand.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.PolicyHandler;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Command to add a new policy.
- */
-@Service
-@Command(scope = "onos", name = "sr-policy-add",
-        description = "Create a new policy")
-public class PolicyAddCommand extends AbstractShellCommand {
-
-    // TODO: Need to support skipping some parameters
-
-    @Argument(index = 0, name = "ID",
-            description = "policy ID",
-            required = true, multiValued = false)
-    String policyId;
-
-    @Argument(index = 1, name = "priority",
-            description = "priority",
-            required = true, multiValued = false)
-    int priority;
-
-    @Argument(index = 2, name = "src_IP",
-            description = "src IP",
-            required = false, multiValued = false)
-    String srcIp;
-
-    @Argument(index = 3, name = "src_port",
-            description = "src port",
-            required = false, multiValued = false)
-    short srcPort;
-
-    @Argument(index = 4, name = "dst_IP",
-            description = "dst IP",
-            required = false, multiValued = false)
-    String dstIp;
-
-    @Argument(index = 5, name = "dst_port",
-            description = "dst port",
-            required = false, multiValued = false)
-    short dstPort;
-
-    @Argument(index = 6, name = "proto",
-            description = "IP protocol",
-            required = false, multiValued = false)
-    String proto;
-
-    @Argument(index = 7, name = "policy_type",
-            description = "policy type",
-            required = true, multiValued = false)
-    String policyType;
-
-    @Argument(index = 8, name = "tunnel_ID",
-            description = "tunnel ID",
-            required = false, multiValued = false)
-    String tunnelId;
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(policyId);
-        tpb.setPriority(priority);
-        tpb.setType(Policy.Type.valueOf(policyType));
-
-        if (srcIp != null) {
-            tpb.setSrcIp(srcIp);
-        }
-        if (dstIp != null) {
-            tpb.setDstIp(dstIp);
-        }
-        if (srcPort != 0) {
-            tpb.setSrcPort(srcPort);
-        }
-        if (dstPort != 0) {
-            tpb.setDstPort(dstPort);
-        }
-        if (!"ip".equals(proto)) {
-            tpb.setIpProto(proto);
-        }
-        if (Policy.Type.valueOf(policyType) == Policy.Type.TUNNEL_FLOW) {
-            if (tunnelId == null) {
-                error("tunnel ID must be specified for TUNNEL_FLOW policy");
-                return;
-            }
-            tpb.setTunnelId(tunnelId);
-        }
-        PolicyHandler.Result result = srService.createPolicy(tpb.build());
-
-        switch (result) {
-            case POLICY_EXISTS:
-                error("the same policy exists");
-                break;
-            case ID_EXISTS:
-                error("the same policy ID exists");
-                break;
-            case TUNNEL_NOT_FOUND:
-                error("the tunnel is not found");
-                break;
-            case UNSUPPORTED_TYPE:
-                error("the policy type specified is not supported");
-                break;
-            default:
-                break;
-        }
-
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyListCommand.java
deleted file mode 100644
index 3520fba..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyListCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Command to show the list of policies.
- */
-@Service
-@Command(scope = "onos", name = "sr-policy-list",
-        description = "Lists all policies")
-public class PolicyListCommand extends AbstractShellCommand {
-
-    private static final String FORMAT_MAPPING_TUNNEL =
-            "  id=%s, type=%s,  prio=%d, src=%s, port=%d, dst=%s, port=%d, proto=%s, tunnel=%s";
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        srService.getPolicies().forEach(policy -> printPolicy(policy));
-    }
-
-    private void printPolicy(Policy policy) {
-        if (policy.type() == Policy.Type.TUNNEL_FLOW) {
-            print(FORMAT_MAPPING_TUNNEL, policy.id(), policy.type(), policy.priority(),
-                    policy.srcIp(), policy.srcPort(), policy.dstIp(), policy.dstPort(),
-                    (policy.ipProto() == null) ? "" : policy.ipProto(),
-                    ((TunnelPolicy) policy).tunnelId());
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyRemoveCommand.java
deleted file mode 100644
index 575d35f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyRemoveCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.PolicyHandler;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Command to remove a policy.
- */
-@Service
-@Command(scope = "onos", name = "sr-policy-remove",
-        description = "Remove a policy")
-public class PolicyRemoveCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "policy ID",
-            description = "policy ID",
-            required = true, multiValued = false)
-    String policyId;
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(policyId);
-        PolicyHandler.Result result = srService.removePolicy(tpb.build());
-        if (result == PolicyHandler.Result.POLICY_NOT_FOUND) {
-            print("ERROR: the policy is not found");
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PortsCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PortsCommand.java
deleted file mode 100644
index f24d28f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PortsCommand.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-@Service
-@Command(scope = "onos", name = "sr-ports", description = "Enable/Disable group of ports on a specific device")
-
-public class PortsCommand extends AbstractShellCommand {
-    @Argument(index = 0, name = "deviceId",
-            description = "Device ID",
-            required = true, multiValued = false)
-    @Completion(DeviceIdCompleter.class)
-    private String deviceIdStr;
-
-    @Argument(index = 1, name = "ports",
-            description = "Ports to be enabled/disabled: ALL, PAIR, INFRA, EDGE",
-            required = true, multiValued = false)
-    @Completion(PlaceholderCompleter.class)
-    private String portsStr;
-
-    @Argument(index = 2, name = "action",
-            description = "Action: ENABLE, DISABLE",
-            required = true, multiValued = false)
-    @Completion(PlaceholderCompleter.class)
-    private String actionStr;
-
-    @Override
-    protected void doExecute() {
-        PhasedRecoveryService prService = get(PhasedRecoveryService.class);
-
-        DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
-
-        boolean enabled;
-        switch (actionStr.toUpperCase()) {
-            case "ENABLE":
-                enabled = true;
-                break;
-            case "DISABLE":
-                enabled = false;
-                break;
-            default:
-                print("Action should be either ENABLE or DISABLE");
-                return;
-        }
-
-        Set<PortNumber> portsChanged;
-        switch (portsStr.toUpperCase()) {
-            case "ALL":
-                portsChanged = prService.changeAllPorts(deviceId, enabled);
-                break;
-            case "PAIR":
-                portsChanged = prService.changePairPort(deviceId, enabled);
-                break;
-            case "INFRA":
-                portsChanged = prService.changeInfraPorts(deviceId, enabled);
-                break;
-            case "EDGE":
-                portsChanged = prService.changeEdgePorts(deviceId, enabled);
-                break;
-            default:
-                print("Ports should be ALL, PAIR, INFRA, EDGE");
-                return;
-        }
-        print("Ports set to %s: %s",
-                enabled ? "enabled" : "disabled",
-                portsChanged.stream().map(PortNumber::toLong).collect(Collectors.toSet()));
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java
deleted file mode 100644
index d595d5c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2017-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.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
-
-
-/**
- * Command to add a pseuwodire.
- */
-@Service
-@Command(scope = "onos", name = "sr-pw-add",
-        description = "Add a pseudowire to the network configuration, if it already exists update it.")
-public class PseudowireAddCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "pwId",
-            description = "Pseudowire ID",
-            required = true, multiValued = false)
-    String pwId;
-
-    @Argument(index = 1, name = "pwLabel",
-            description = "Pseudowire Label",
-            required = true, multiValued = false)
-    String pwLabel;
-
-    @Argument(index = 2, name = "mode",
-            description = "Mode used for pseudowire",
-            required = true, multiValued = false)
-    String mode;
-
-    @Argument(index = 3, name = "sDTag",
-            description = "Service delimiting tag",
-            required = true, multiValued = false)
-    String sDTag;
-
-    @Argument(index = 4, name = "cP1",
-            description = "Connection Point 1",
-            required = true, multiValued = false)
-    String cP1;
-
-    @Argument(index = 5, name = "cP1InnerVlan",
-            description = "Inner Vlan of Connection Point 1",
-            required = true, multiValued = false)
-    String cP1InnerVlan;
-
-    @Argument(index = 6, name = "cP1OuterVlan",
-            description = "Outer Vlan of Connection Point 1",
-            required = true, multiValued = false)
-    String cP1OuterVlan;
-
-    @Argument(index = 7, name = "cP2",
-            description = "Connection Point 2",
-            required = true, multiValued = false)
-    String cP2;
-
-    @Argument(index = 8, name = "cP2InnerVlan",
-            description = "Inner Vlan of Connection Point 2",
-            required = true, multiValued = false)
-    String cP2InnerVlan;
-
-    @Argument(index = 9, name = "cP2OuterVlan",
-            description = "Outer Vlan of Connection Point 2",
-            required = true, multiValued = false)
-    String cP2OuterVlan;
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        L2Tunnel tun;
-        L2TunnelPolicy policy;
-
-        try {
-            tun = new DefaultL2Tunnel(parseMode(mode), parseVlan(sDTag), parsePwId(pwId), parsePWLabel(pwLabel));
-        } catch (IllegalArgumentException e) {
-            log.error("Exception while parsing L2Tunnel : \n\t %s", e.getMessage());
-            print("Exception while parsing L2Tunnel : \n\t %s", e.getMessage());
-            return;
-        }
-
-        try {
-            policy = new DefaultL2TunnelPolicy(parsePwId(pwId),
-                                               ConnectPoint.deviceConnectPoint(cP1), parseVlan(cP1InnerVlan),
-                                               parseVlan(cP1OuterVlan), ConnectPoint.deviceConnectPoint(cP2),
-                                               parseVlan(cP2InnerVlan), parseVlan(cP2OuterVlan));
-
-        } catch (IllegalArgumentException e) {
-            log.error("Exception while parsing L2TunnelPolicy : \n\t %s", e.getMessage());
-            print("Exception while parsing L2TunnelPolicy : \n\t %s", e.getMessage());
-            return;
-        }
-
-        L2TunnelDescription pw = new DefaultL2TunnelDescription(tun, policy);
-        L2TunnelHandler.Result res = srService.addPseudowire(pw);
-        log.info("Deploying pseudowire {} via the command line.", pw);
-        switch (res) {
-            case WRONG_PARAMETERS:
-                print("Pseudowire could not be added , error in the parameters : \n\t%s",
-                      res.getSpecificError());
-                break;
-            case CONFIGURATION_ERROR:
-                print("Pseudowire could not be added, configuration error : \n\t%s",
-                      res.getSpecificError());
-                break;
-            case PATH_NOT_FOUND:
-                print("Pseudowire path not found : \n\t%s",
-                      res.getSpecificError());
-                break;
-            case INTERNAL_ERROR:
-                print("Pseudowire could not be added, internal error : \n\t%s",
-                      res.getSpecificError());
-                break;
-            case SUCCESS:
-                break;
-            default:
-                break;
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireIdCompleter.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireIdCompleter.java
deleted file mode 100644
index abf0c0c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireIdCompleter.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2014-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.cli;
-
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.stream.Collectors;
-
-/**
- * Device ID completer.
- */
-@Service
-public class PseudowireIdCompleter implements Completer {
-    @Override
-    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
-        // Delegate string completer
-        StringsCompleter delegate = new StringsCompleter();
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-
-        List<L2Tunnel> tunnels = srService.getL2Tunnels();
-
-        // combine polices and tunnels to pseudowires
-        Iterator<String> pseudowires = tunnels.stream()
-                .map(l2Tunnel -> Long.toString(l2Tunnel.tunnelId()))
-                .collect(Collectors.toList()).iterator();
-
-        SortedSet<String> strings = delegate.getStrings();
-        while (pseudowires.hasNext()) {
-            strings.add(pseudowires.next());
-        }
-
-        // Now let the completer do the work for figuring out what to offer.
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireListCommand.java
deleted file mode 100644
index 475ce26..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireListCommand.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2017-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-/**
- * Command to show the pseudowires.
- */
-@Service
-@Command(scope = "onos", name = "sr-pw-list",
-        description = "Lists all pseudowires")
-public class PseudowireListCommand extends AbstractShellCommand {
-
-    private static final String FORMAT_PSEUDOWIRE =
-            "Pseudowire id = %s \n" +
-                    "   mode : %s, sdTag : %s, pwLabel : %s \n" +
-                    "   cP1 : %s , cP1OuterTag : %s, cP1InnerTag : %s \n" +
-                    "   cP2 : %s , cP2OuterTag : %s, cP2InnerTag : %s \n" +
-                    "   transportVlan : %s \n" +
-                    "   pending = %s";
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        srService.getL2TunnelDescriptions(false)
-                .forEach(pw -> printPseudowire(pw, false));
-
-        srService.getL2TunnelDescriptions(true)
-                .forEach(pw -> printPseudowire(pw, true));
-    }
-
-    private void printPseudowire(L2TunnelDescription pseudowire, boolean pending) {
-        VlanId vlan = pseudowire.l2Tunnel().transportVlan().equals(VlanId.vlanId((short) 4094)) ?
-                VlanId.NONE : pseudowire.l2Tunnel().transportVlan();
-
-        print(FORMAT_PSEUDOWIRE, pseudowire.l2Tunnel().tunnelId(), pseudowire.l2Tunnel().pwMode(),
-              pseudowire.l2Tunnel().sdTag(), pseudowire.l2Tunnel().pwLabel(),
-              pseudowire.l2TunnelPolicy().cP1(), pseudowire.l2TunnelPolicy().cP1OuterTag(),
-              pseudowire.l2TunnelPolicy().cP1InnerTag(), pseudowire.l2TunnelPolicy().cP2(),
-              pseudowire.l2TunnelPolicy().cP2OuterTag(), pseudowire.l2TunnelPolicy().cP2InnerTag(),
-              vlan, pending);
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireNextListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireNextListCommand.java
deleted file mode 100644
index f2b3e8d..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireNextListCommand.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the pseudowire next stores.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-pw",
-        description = "Displays the current next-id for pseudowire")
-public class PseudowireNextListCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        print(srService.getPwInitNext());
-        print(srService.getPwTermNext());
-    }
-
-    private void print(Map<String, NextObjective> nextStore) {
-        ArrayList<String> a = new ArrayList<>(nextStore.keySet());
-        a.sort(Comparator.comparing((String o) -> o));
-
-        StringBuilder builder = new StringBuilder();
-        a.forEach(k ->
-            builder.append("\n")
-                    .append(k)
-                    .append(" --> ")
-                    .append(nextStore.get(k).id())
-        );
-        print(builder.toString());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java
deleted file mode 100644
index 2bb28b0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2017-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.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.parsePwId;
-
-
-/**
- * Command to remove a pseudowire.
- */
-@Service
-@Command(scope = "onos", name = "sr-pw-remove",
-        description = "Remove a pseudowire")
-public class PseudowireRemoveCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "pwId",
-            description = "pseudowire ID",
-            required = true, multiValued = false)
-    @Completion(PseudowireIdCompleter.class)
-    String pwId;
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        // remove the pseudowire
-        SegmentRoutingManager mngr = (SegmentRoutingManager) srService;
-        int pwIntId;
-        try {
-            pwIntId = parsePwId(pwId);
-        } catch (IllegalArgumentException e) {
-            log.error("Exception while parsing pseudowire id : \n\t %s", e.getMessage());
-            print("Exception while parsing pseudowire id : \n\t %s", e.getMessage());
-            return;
-        }
-
-        log.info("Removing pseudowire {} from the command line.", pwIntId);
-        L2TunnelHandler.Result res = mngr.removePseudowire(pwIntId);
-        switch (res) {
-            case WRONG_PARAMETERS:
-                error("Pseudowire could not be removed , wrong parameters: \n\t %s\n",
-                      res.getSpecificError());
-                break;
-            case INTERNAL_ERROR:
-                error("Pseudowire could not be removed, internal error : \n\t %s\n",
-                      res.getSpecificError());
-                break;
-            case SUCCESS:
-                break;
-            default:
-                break;
-            }
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/RerouteNetworkCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/RerouteNetworkCommand.java
deleted file mode 100644
index 6e8d3e9..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/RerouteNetworkCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016-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.cli;
-
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Command to manually trigger routing and rule-population in the network.
- *
- */
-@Service
-@Command(scope = "onos", name = "sr-reroute-network",
-        description = "Repopulate routing rules given current network state")
-public class RerouteNetworkCommand extends AbstractShellCommand {
-
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-        srService.rerouteNetwork();
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/ShouldProgramCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/ShouldProgramCommand.java
deleted file mode 100644
index 250fb3b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/ShouldProgramCommand.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Display current shouldProgram map.
- */
-@Service
-@Command(scope = "onos", name = "sr-should-program",
-        description = "Display current shouldProgram map")
-public class ShouldProgramCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService = AbstractShellCommand.get(SegmentRoutingService.class);
-        Map<Set<DeviceId>, NodeId> shouldProgram = srService.getShouldProgram();
-        Map<DeviceId, Boolean> shouldProgramCache = srService.getShouldProgramCache();
-
-        print("shouldProgram");
-        shouldProgram.forEach((k, v) -> print("%s -> %s", k, v));
-
-        print("shouldProgramCache");
-        shouldProgramCache.forEach((k, v) -> print("%s -> %s", k, v));
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelAddCommand.java
deleted file mode 100644
index 0e487d0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelAddCommand.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.DefaultTunnel;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-import org.onosproject.segmentrouting.TunnelHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-/**
- * Command to add a new tunnel.
- */
-@Service
-@Command(scope = "onos", name = "sr-tunnel-add",
-        description = "Create a new tunnel")
-public class TunnelAddCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "tunnel ID",
-            description = "tunnel ID",
-            required = true, multiValued = false)
-    String tunnelId;
-
-    @Argument(index = 1, name = "label path",
-            description = "label path",
-            required = true, multiValued = false)
-    String labels;
-
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        List<Integer> labelIds = new ArrayList<>();
-        StringTokenizer strToken = new StringTokenizer(labels, ",");
-        while (strToken.hasMoreTokens()) {
-            labelIds.add(Integer.valueOf(strToken.nextToken()));
-        }
-        Tunnel tunnel = new DefaultTunnel(tunnelId, labelIds);
-
-        TunnelHandler.Result result = srService.createTunnel(tunnel);
-        switch (result) {
-            case ID_EXISTS:
-                print("ERROR: the same tunnel ID exists");
-                break;
-            case TUNNEL_EXISTS:
-                print("ERROR: the same tunnel exists");
-                break;
-            case INTERNAL_ERROR:
-                print("ERROR: internal tunnel creation error");
-                break;
-            case WRONG_PATH:
-                print("ERROR: the tunnel path is wrong");
-                break;
-            default:
-                break;
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelListCommand.java
deleted file mode 100644
index 6c5f33d..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelListCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-
-/**
- * Command to show the list of tunnels.
- */
-@Service
-@Command(scope = "onos", name = "sr-tunnel-list",
-        description = "Lists all tunnels")
-public class TunnelListCommand extends AbstractShellCommand {
-
-    private static final String FORMAT_MAPPING =
-            "  id=%s, path=%s";
-
-    @Override
-    protected void doExecute() {
-
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        srService.getTunnels().forEach(tunnel -> printTunnel(tunnel));
-    }
-
-    private void printTunnel(Tunnel tunnel) {
-        print(FORMAT_MAPPING, tunnel.id(), tunnel.labelIds());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelRemoveCommand.java
deleted file mode 100644
index f5f0299..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelRemoveCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.cli;
-
-
-import com.google.common.collect.Lists;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.DefaultTunnel;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-import org.onosproject.segmentrouting.TunnelHandler;
-
-/**
- * Command to remove a tunnel.
- */
-@Service
-@Command(scope = "onos", name = "sr-tunnel-remove",
-        description = "Remove a tunnel")
-public class TunnelRemoveCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "tunnel ID",
-            description = "tunnel ID",
-            required = true, multiValued = false)
-    String tunnelId;
-
-    @Override
-    protected void doExecute() {
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        Tunnel tunnel = new DefaultTunnel(tunnelId, Lists.newArrayList());
-        TunnelHandler.Result result = srService.removeTunnel(tunnel);
-        switch (result) {
-            case TUNNEL_IN_USE:
-                print("ERROR: the tunnel is still in use");
-                break;
-            case TUNNEL_NOT_FOUND:
-                print("ERROR: the tunnel is not found");
-                break;
-            default:
-                break;
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/VerifyGroupsCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/VerifyGroupsCommand.java
deleted file mode 100644
index 385260e..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/VerifyGroupsCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2017-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.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Triggers the verification of hashed group buckets in the specified device,
- * and corrects the buckets if necessary. Outcome can be viewed in the 'groups'
- * command.
- */
-@Service
-@Command(scope = "onos", name = "sr-verify-groups",
-        description = "Triggers the verification of hashed groups in the specified "
-                + "device. Does not return any output; users can query the results "
-                + "in the 'groups' command")
-public class VerifyGroupsCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "uri", description = "Device ID",
-            required = true, multiValued = false)
-    @Completion(DeviceIdCompleter.class)
-    String uri = null;
-
-    @Override
-    protected void doExecute() {
-        DeviceService deviceService = get(DeviceService.class);
-        SegmentRoutingService srService =
-                AbstractShellCommand.get(SegmentRoutingService.class);
-
-        if (uri != null) {
-            Device dev = deviceService.getDevice(DeviceId.deviceId(uri));
-            if (dev != null) {
-                srService.verifyGroups(dev.id());
-            }
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectAddCommand.java
deleted file mode 100644
index 22daeb5..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectAddCommand.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import com.google.common.collect.Sets;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.cli.net.PortNumberCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectPortEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-import java.util.Set;
-
-/**
- * Creates Xconnect.
- */
-@Service
-@Command(scope = "onos", name = "sr-xconnect-add", description = "Create Xconnect")
-public class XconnectAddCommand extends AbstractShellCommand {
-    private static final String EP_DESC = "Can be a physical port number or a load balancer key. " +
-            "Use integer to specify physical port number. " +
-            "Use " + XconnectPortEndpoint.LB_KEYWORD + "key to specify load balancer key";
-
-    @Argument(index = 0, name = "deviceId",
-            description = "Device ID",
-            required = true, multiValued = false)
-    @Completion(DeviceIdCompleter.class)
-    private String deviceIdStr;
-
-    @Argument(index = 1, name = "vlanId",
-            description = "VLAN ID",
-            required = true, multiValued = false)
-    @Completion(PlaceholderCompleter.class)
-    private String vlanIdStr;
-
-    @Argument(index = 2, name = "ep1",
-            description = "First endpoint. " + EP_DESC,
-            required = true, multiValued = false)
-    @Completion(PortNumberCompleter.class)
-    private String ep1Str;
-
-    @Argument(index = 3, name = "ep2",
-            description = "Second endpoint. " + EP_DESC,
-            required = true, multiValued = false)
-    @Completion(PortNumberCompleter.class)
-    private String ep2Str;
-
-    private static final String L2LB_PATTERN = "^(\\d*|L2LB\\(\\d*\\))$";
-
-    @Override
-    protected void doExecute() {
-        DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
-        VlanId vlanId = VlanId.vlanId(vlanIdStr);
-
-        XconnectEndpoint ep1 = XconnectEndpoint.fromString(ep1Str);
-        XconnectEndpoint ep2 = XconnectEndpoint.fromString(ep2Str);
-
-        Set<XconnectEndpoint> endpoints = Sets.newHashSet(ep1, ep2);
-
-        XconnectService xconnectService = get(XconnectService.class);
-        xconnectService.addOrUpdateXconnect(deviceId, vlanId, endpoints);
-    }
-
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectListCommand.java
deleted file mode 100644
index 44a7d37..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectListCommand.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-/**
- * Lists Xconnects.
- */
-@Service
-@Command(scope = "onos", name = "sr-xconnect", description = "Lists all Xconnects")
-public class XconnectListCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        XconnectService xconnectService = get(XconnectService.class);
-        xconnectService.getXconnects().forEach(desc -> print("%s", desc));
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectNextListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectNextListCommand.java
deleted file mode 100644
index 0b81186..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectNextListCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.xconnect.api.XconnectKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the xconnect next stores.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-xconnect",
-        description = "Displays the current next-id for xconnect")
-public class XconnectNextListCommand extends AbstractShellCommand {
-    @Override
-    protected void doExecute() {
-        XconnectService xconnectService =
-                AbstractShellCommand.get(XconnectService.class);
-        print(xconnectService.getNext());
-    }
-
-    private void print(Map<XconnectKey, Integer> nextStore) {
-        ArrayList<XconnectKey> a = new ArrayList<>(nextStore.keySet());
-        a.sort(Comparator
-                .comparing((XconnectKey o) -> o.deviceId().toString())
-                .thenComparing((XconnectKey o) -> o.vlanId().toShort()));
-
-        StringBuilder builder = new StringBuilder();
-        a.forEach(k ->
-            builder.append("\n")
-                    .append(k)
-                    .append(" --> ")
-                    .append(nextStore.get(k))
-        );
-        print(builder.toString());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectRemoveCommand.java
deleted file mode 100644
index e651338..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectRemoveCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2018-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.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-/**
- * Deletes Xconnect.
- */
-@Service
-@Command(scope = "onos", name = "sr-xconnect-remove", description = "Remove Xconnect")
-public class XconnectRemoveCommand extends AbstractShellCommand {
-    @Argument(index = 0, name = "deviceId",
-            description = "Device ID",
-            required = true, multiValued = false)
-    @Completion(DeviceIdCompleter.class)
-    private String deviceIdStr;
-
-    @Argument(index = 1, name = "vlanId",
-            description = "VLAN ID",
-            required = true, multiValued = false)
-    @Completion(PlaceholderCompleter.class)
-    private String vlanIdStr;
-
-    @Override
-    protected void doExecute() {
-        DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
-        VlanId vlanId = VlanId.vlanId(vlanIdStr);
-
-        XconnectService xconnectService = get(XconnectService.class);
-        xconnectService.removeXonnect(deviceId, vlanId);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/package-info.java
deleted file mode 100644
index 0f2cea6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Segment routing application CLI handlers.
- */
-package org.onosproject.segmentrouting.cli;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/BlockedPortsConfig.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/BlockedPortsConfig.java
deleted file mode 100644
index a5c5557..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/BlockedPortsConfig.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2017-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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.config.Config;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Network config to describe ports that should be blocked until authenticated.
- */
-public class BlockedPortsConfig extends Config<ApplicationId> {
-
-    /**
-     * Returns the top level keys to the config,
-     * which should be device ID strings.
-     *
-     * @return this list of top level keys
-     */
-    public List<String> deviceIds() {
-        List<String> devIds = new ArrayList<>();
-        if (object != null) {
-            Iterator<String> it = object.fieldNames();
-            if (it != null) {
-                it.forEachRemaining(devIds::add);
-            }
-        }
-        return devIds;
-    }
-
-    /**
-     * Returns the port range strings associated with the given device id key.
-     *
-     * @param deviceId the device id key
-     * @return the associated port range strings
-     */
-    public List<String> portRanges(String deviceId) {
-        List<String> portRanges = new ArrayList<>();
-        if (object != null) {
-            JsonNode jnode = object.get(deviceId);
-            if (ArrayNode.class.isInstance(jnode)) {
-                ArrayNode array = (ArrayNode) jnode;
-                array.forEach(pr -> portRanges.add(pr.asText()));
-            }
-        }
-        return portRanges;
-    }
-
-    /**
-     * Returns an iterator over the port numbers defined by the port ranges
-     * defined in the configuration, for the given device.
-     *
-     * @param deviceId the specific device
-     * @return an iterator over the configured ports
-     */
-    public Iterator<Long> portIterator(String deviceId) {
-        List<String> ranges = portRanges(deviceId);
-        return new PortIterator(ranges);
-    }
-
-    /**
-     * Private implementation of an iterator that aggregates several range
-     * iterators into a single iterator.
-     */
-    class PortIterator implements Iterator<Long> {
-        private final List<Range> ranges;
-        private final int nRanges;
-        private int currentRange = 0;
-        private Iterator<Long> iterator;
-
-        PortIterator(List<String> rangeSpecs) {
-            nRanges = rangeSpecs.size();
-            ranges = new ArrayList<>(nRanges);
-            if (nRanges > 0) {
-                for (String rs : rangeSpecs) {
-                    ranges.add(new Range(rs));
-                }
-                iterator = ranges.get(0).iterator();
-            }
-        }
-
-        @Override
-        public boolean hasNext() {
-            return nRanges > 0 &&
-                    (currentRange < nRanges - 1 ||
-                            (currentRange < nRanges && iterator.hasNext()));
-        }
-
-        @Override
-        public Long next() {
-            if (nRanges == 0) {
-                throw new NoSuchElementException();
-            }
-
-            Long value;
-            if (iterator.hasNext()) {
-                value = iterator.next();
-            } else {
-                currentRange++;
-                if (currentRange < nRanges) {
-                    iterator = ranges.get(currentRange).iterator();
-                    value = iterator.next();
-                } else {
-                    throw new NoSuchElementException();
-                }
-            }
-            return value;
-        }
-    }
-
-    /**
-     * Private implementation of a "range" of long numbers, defined by a
-     * string of the form {@code "<lo>-<hi>"}, for example, "17-32".
-     */
-    static final class Range {
-        private static final Pattern RE_SINGLE = Pattern.compile("(\\d+)");
-        private static final Pattern RE_RANGE = Pattern.compile("(\\d+)-(\\d+)");
-        private static final String E_BAD_FORMAT = "Bad Range Format ";
-
-        private final long lo;
-        private final long hi;
-
-        /**
-         * Constructs a range from the given string definition.
-         * For example:
-         * <pre>
-         *     Range r = new Range("17-32");
-         * </pre>
-         *
-         * @param s the string representation of the range
-         * @throws IllegalArgumentException if the range string is malformed
-         */
-        Range(String s) {
-            String lohi = s;
-            Matcher m = RE_SINGLE.matcher(s);
-            if (m.matches()) {
-                lohi = s + "-" + s;
-            }
-            m = RE_RANGE.matcher(lohi);
-            if (!m.matches()) {
-                throw new IllegalArgumentException(E_BAD_FORMAT + s);
-            }
-            try {
-                lo = Long.parseLong(m.group(1));
-                hi = Long.parseLong(m.group(2));
-
-                if (hi < lo) {
-                    throw new IllegalArgumentException(E_BAD_FORMAT + s);
-                }
-            } catch (NumberFormatException nfe) {
-                // unlikely to be thrown, since the matcher will have failed first
-                throw new IllegalArgumentException(E_BAD_FORMAT + s, nfe);
-            }
-        }
-
-
-        /**
-         * Returns an iterator over this range, starting from the lowest value
-         * and iterating up to the highest value (inclusive).
-         *
-         * @return an iterator over this range
-         */
-        Iterator<Long> iterator() {
-            return new RangeIterator();
-        }
-
-        /**
-         * Private implementation of an iterator over the range.
-         */
-        class RangeIterator implements Iterator<Long> {
-            long current;
-
-            RangeIterator() {
-                current = lo - 1;
-            }
-
-            @Override
-            public boolean hasNext() {
-                return current < hi;
-            }
-
-            @Override
-            public Long next() {
-                if (!hasNext()) {
-                    throw new NoSuchElementException();
-                }
-                return ++current;
-            }
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java
deleted file mode 100644
index 773c7f6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.config;
-
-/**
- * Signals that an error occurred during reading device configuration.
- */
-public class DeviceConfigNotFoundException extends Exception {
-
-    /**
-     * Creates a new ConfigNotFoundException with the given message.
-     *
-     * @param message exception message
-     */
-    public DeviceConfigNotFoundException(String message) {
-        super(message);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
deleted file mode 100644
index d161f63..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * 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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.HostId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.ConfigException;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.routeservice.Route;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Segment Routing configuration component that reads the
- * segment routing related configuration from Network Configuration Manager
- * component and organizes in more accessible formats.
- */
-public class DeviceConfiguration implements DeviceProperties {
-
-    private static final String NO_SUBNET = "No subnet configured on {}";
-
-    private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
-    private final List<Integer> allSegmentIds = new ArrayList<>();
-    private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
-    private SegmentRoutingManager srManager;
-
-    private class SegmentRouterInfo {
-        int ipv4NodeSid = -1;
-        int ipv6NodeSid = -1;
-        DeviceId deviceId;
-        Ip4Address ipv4Loopback;
-        Ip6Address ipv6Loopback;
-        MacAddress mac;
-        boolean isEdge;
-        SetMultimap<PortNumber, IpAddress> gatewayIps;
-        SetMultimap<PortNumber, IpPrefix> subnets;
-        Map<Integer, Set<Integer>> adjacencySids;
-        DeviceId pairDeviceId;
-        PortNumber pairLocalPort;
-        int pwRoutingLabel;
-
-        public SegmentRouterInfo() {
-            gatewayIps = Multimaps.synchronizedSetMultimap(HashMultimap.create());
-            subnets = Multimaps.synchronizedSetMultimap(HashMultimap.create());
-        }
-    }
-
-    /**
-     * Constructs device configuration for all Segment Router devices,
-     * organizing the data into various maps for easier access.
-     *
-     * @param srManager Segment Routing Manager
-     */
-    public DeviceConfiguration(SegmentRoutingManager srManager) {
-        this.srManager = srManager;
-        updateConfig();
-    }
-
-    public void updateConfig() {
-        // Read config from device subject, excluding gatewayIps and subnets.
-        Set<DeviceId> deviceSubjects =
-                srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
-        deviceSubjects.forEach(subject -> {
-            BasicDeviceConfig basicDeviceConfig = srManager.cfgService.addConfig(subject, BasicDeviceConfig.class);
-            if (!basicDeviceConfig.purgeOnDisconnection()) {
-                // Setting purge on disconnection flag for the device SR has control over.
-                // addConfig returns a config if it exists or creates a new one.
-                log.info("PurgeOnDisconnection set to true for device {}", subject);
-                basicDeviceConfig.purgeOnDisconnection(true);
-                srManager.cfgService.applyConfig(subject, BasicDeviceConfig.class, basicDeviceConfig.node());
-            }
-            SegmentRoutingDeviceConfig config =
-                    srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
-            SegmentRouterInfo info = new SegmentRouterInfo();
-            info.deviceId = subject;
-            info.ipv4NodeSid = config.nodeSidIPv4();
-            info.ipv6NodeSid = config.nodeSidIPv6();
-            info.ipv4Loopback = config.routerIpv4();
-            info.ipv6Loopback = config.routerIpv6();
-            info.mac = config.routerMac();
-            info.isEdge = config.isEdgeRouter();
-            info.adjacencySids = config.adjacencySids();
-            info.pairDeviceId = config.pairDeviceId();
-            info.pairLocalPort = config.pairLocalPort();
-            info.pwRoutingLabel = info.ipv4NodeSid + 1000;
-            deviceConfigMap.put(info.deviceId, info);
-            log.debug("Read device config for device: {}", info.deviceId);
-            /*
-             * IPv6 sid is not inserted. this part of the code is not used for now.
-             */
-            allSegmentIds.add(info.ipv4NodeSid);
-        });
-
-        // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
-        Set<ConnectPoint> portSubjects = srManager.cfgService
-                .getSubjects(ConnectPoint.class, InterfaceConfig.class);
-        portSubjects.stream()
-                .filter(subject -> deviceConfigMap.containsKey(subject.deviceId()))
-                .filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
-            InterfaceConfig config =
-                    srManager.cfgService.getConfig(subject, InterfaceConfig.class);
-            Set<Interface> networkInterfaces;
-            try {
-                networkInterfaces = config.getInterfaces();
-            } catch (ConfigException e) {
-                log.error("Error loading port configuration");
-                return;
-            }
-            networkInterfaces.forEach(networkInterface -> {
-                VlanId vlanId = networkInterface.vlan();
-                ConnectPoint connectPoint = networkInterface.connectPoint();
-                DeviceId dpid = connectPoint.deviceId();
-                PortNumber port = connectPoint.port();
-                MacAddress mac = networkInterface.mac();
-                SegmentRouterInfo info = deviceConfigMap.get(dpid);
-
-                // skip if there is no corresponding device for this ConenctPoint
-                if (info != null) {
-                    // Extract subnet information
-                    List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
-                    interfaceAddresses.forEach(interfaceAddress -> {
-                        // Do not add /0, /32 and /128 to gateway IP list
-                        int prefixLength = interfaceAddress.subnetAddress().prefixLength();
-                        IpPrefix ipPrefix = interfaceAddress.subnetAddress();
-                        if (ipPrefix.isIp4()) {
-                            if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
-                                info.gatewayIps.put(port, interfaceAddress.ipAddress());
-                            }
-                            info.subnets.put(port, interfaceAddress.subnetAddress());
-                        } else {
-                            if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET6_MASK_LENGTH) {
-                                info.gatewayIps.put(port, interfaceAddress.ipAddress());
-                            }
-                            info.subnets.put(port, interfaceAddress.subnetAddress());
-                        }
-                    });
-
-                    // Override interface mac with router mac
-                    if (!mac.equals(info.mac)) {
-                        ArrayNode array = (ArrayNode) config.node();
-                        for (JsonNode intfNode : array) {
-                            ObjectNode objNode = (ObjectNode) intfNode;
-                            objNode.put(InterfaceConfig.MAC, info.mac.toString());
-                        }
-                        srManager.cfgService.applyConfig(connectPoint, InterfaceConfig.class, array);
-                    }
-                }
-            });
-            // We register the connect point with the NRS.
-            srManager.registerConnectPoint(subject);
-        });
-    }
-
-    public Collection<DeviceId> getRouters() {
-        return deviceConfigMap.keySet();
-    }
-
-    @Override
-    public boolean isConfigured(DeviceId deviceId) {
-        return deviceConfigMap.get(deviceId) != null;
-    }
-
-    @Override
-    public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
-            return srinfo.ipv4NodeSid;
-        } else {
-            String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    @Override
-    public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
-            return srinfo.ipv6NodeSid;
-        } else {
-            String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    @Override
-    public int getPWRoutingLabel(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            log.trace("pwRoutingLabel for device{} is {}", deviceId, srinfo.pwRoutingLabel);
-            return srinfo.pwRoutingLabel;
-        } else {
-            String message = "getPWRoutingLabel fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    /**
-     * Returns the IPv4 Node segment id of a segment router given its Router mac address.
-     *
-     * @param routerMac router mac address
-     * @return node segment id, or -1 if not found in config
-     */
-    public int getIPv4SegmentId(MacAddress routerMac) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
-                    deviceConfigMap.entrySet()) {
-            if (entry.getValue().mac.equals(routerMac)) {
-                return entry.getValue().ipv4NodeSid;
-            }
-        }
-
-        return -1;
-    }
-
-    /**
-     * Returns the IPv6 Node segment id of a segment router given its Router mac address.
-     *
-     * @param routerMac router mac address
-     * @return node segment id, or -1 if not found in config
-     */
-    public int getIPv6SegmentId(MacAddress routerMac) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
-                deviceConfigMap.entrySet()) {
-            if (entry.getValue().mac.equals(routerMac)) {
-                return entry.getValue().ipv6NodeSid;
-            }
-        }
-
-        return -1;
-    }
-
-    /**
-     * Returns the IPv4 Node segment id of a segment router given its Router ip address.
-     *
-     * @param routerAddress router ip address
-     * @return node segment id, or -1 if not found in config
-     */
-    public int getIPv4SegmentId(Ip4Address routerAddress) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
-            Ip4Address ipv4Loopback = entry.getValue().ipv4Loopback;
-            if (ipv4Loopback == null) {
-                continue;
-            }
-            if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
-                if (entry.getValue().ipv4NodeSid == -1) {
-                    continue;
-                }
-                return entry.getValue().ipv4NodeSid;
-            }
-        }
-
-        return -1;
-    }
-
-    /**
-     * Returns the IPv6 Node segment id of a segment router given its Router ip address.
-     *
-     * @param routerAddress router ip address
-     * @return node segment id, or -1 if not found in config
-     */
-    public int getIPv6SegmentId(Ip6Address routerAddress) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
-            Ip6Address ipv6Loopback = entry.getValue().ipv6Loopback;
-            if (ipv6Loopback == null) {
-                continue;
-            }
-            if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
-                if (entry.getValue().ipv6NodeSid == -1) {
-                    continue;
-                }
-                return entry.getValue().ipv6NodeSid;
-            }
-        }
-
-        return -1;
-    }
-
-    @Override
-    public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            return srinfo.mac;
-        } else {
-            String message = "getDeviceMac fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    @Override
-    public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
-            return srinfo.ipv4Loopback;
-        } else {
-            String message = "getRouterIpv4 fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    @Override
-    public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
-            return srinfo.ipv6Loopback;
-        } else {
-            String message = "getRouterIpv6 fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    /**
-     * Gets router ip address based on the destination ip address.
-     *
-     * @param destIpAddress the destination ip address
-     * @param routerDeviceId the device id
-     * @return the ip address of the routes
-     */
-    public IpAddress getRouterIpAddress(IpAddress destIpAddress, DeviceId routerDeviceId) {
-        IpAddress routerIpAddress;
-        try {
-            routerIpAddress = destIpAddress.isIp4() ? getRouterIpv4(routerDeviceId) :
-                    getRouterIpv6(routerDeviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            routerIpAddress = null;
-        }
-        return routerIpAddress;
-    }
-
-    @Override
-    public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
-            return srinfo.isEdge;
-        } else {
-            String message = "isEdgeDevice fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    @Override
-    public List<Integer> getAllDeviceSegmentIds() {
-        return allSegmentIds;
-    }
-
-    @Override
-    public Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
-            throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo == null) {
-            String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-        // Construct subnet-port mapping from port-subnet mapping
-        SetMultimap<PortNumber, IpPrefix> portSubnetMap = srinfo.subnets;
-        Map<IpPrefix, List<PortNumber>> subnetPortMap = new HashMap<>();
-
-        portSubnetMap.entries().forEach(entry -> {
-            PortNumber port = entry.getKey();
-            IpPrefix subnet = entry.getValue();
-
-            if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
-                    subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
-                return;
-            }
-
-            if (subnetPortMap.containsKey(subnet)) {
-                subnetPortMap.get(subnet).add(port);
-            } else {
-                ArrayList<PortNumber> ports = new ArrayList<>();
-                ports.add(port);
-                subnetPortMap.put(subnet, ports);
-            }
-        });
-        return subnetPortMap;
-    }
-
-    /**
-     * Returns the device identifier or data plane identifier (dpid)
-     * of a segment router given its segment id.
-     *
-     * @param sid segment id
-     * @return deviceId device identifier
-     */
-    public DeviceId getDeviceId(int sid) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
-            deviceConfigMap.entrySet()) {
-            if (entry.getValue().ipv4NodeSid == sid ||
-                    entry.getValue().ipv6NodeSid == sid) {
-                return entry.getValue().deviceId;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the device identifier or data plane identifier (dpid)
-     * of a segment router given its router ip address.
-     *
-     * @param ipAddress router ip address
-     * @return deviceId device identifier
-     */
-    public DeviceId getDeviceId(Ip4Address ipAddress) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
-            deviceConfigMap.entrySet()) {
-            if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
-                return entry.getValue().deviceId;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the device identifier or data plane identifier (dpid)
-     * of a segment router given its router ipv6 address.
-     *
-     * @param ipAddress router ipv6 address
-     * @return deviceId device identifier
-     */
-    public DeviceId getDeviceId(Ip6Address ipAddress) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
-                deviceConfigMap.entrySet()) {
-            if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
-                return entry.getValue().deviceId;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the configured port ip addresses for a segment router.
-     * These addresses serve as gateway IP addresses for the subnets configured
-     * on those ports.
-     *
-     * @param deviceId device identifier
-     * @return immutable set of ip addresses configured on the ports or null if not found
-     */
-    public Set<IpAddress> getPortIPs(DeviceId deviceId) {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
-                      srinfo.gatewayIps.values());
-            return ImmutableSet.copyOf(srinfo.gatewayIps.values());
-        }
-        return null;
-    }
-
-    /**
-     * Returns configured subnets for a segment router.
-     *
-     * @param deviceId device identifier
-     * @return list of ip prefixes or null if not found
-     */
-    public Set<IpPrefix> getConfiguredSubnets(DeviceId deviceId) {
-        Set<IpPrefix> subnets = srManager.interfaceService.getInterfaces().stream()
-                .filter(intf -> Objects.equals(deviceId, intf.connectPoint().deviceId()))
-                .flatMap(intf -> intf.ipAddressesList().stream())
-                .map(InterfaceIpAddress::subnetAddress)
-                .collect(Collectors.toSet());
-
-        if (subnets.isEmpty()) {
-            log.debug(NO_SUBNET, deviceId);
-            return Collections.emptySet();
-        }
-        return subnets;
-    }
-
-    /**
-     * Returns all subnets for a segment router, including subnets learnt from route service.
-     *
-     * @param deviceId device identifier
-     * @return set of ip prefixes or null if not found
-     * @deprecated use getBatchedSubnets(DeviceId deviceId) instead
-     */
-    @Deprecated
-    public Set<IpPrefix> getSubnets(DeviceId deviceId) {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null && srinfo.subnets != null) {
-            // Note: ImmutableSet.Builder.addAll calls the iterator of parameter internally,
-            //       which is not protected by SynchronizedCollection mutex.
-            ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
-            srinfo.subnets.forEach((k, v) -> builder.add(v));
-            return builder.build();
-        }
-        return null;
-    }
-
-    /**
-     * Returns batches of all subnets reachable via given next hop
-     * <p>
-     * First batch includes FPM and STATIC routes
-     * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
-     *
-     * @param hostId next hop host id
-     * @return list of subnet batches, each batch includes a set of prefixes.
-     */
-    // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
-    public List<Set<IpPrefix>> getBatchedSubnets(HostId hostId) {
-        Set<IpPrefix> high = Sets.newHashSet();
-        Set<IpPrefix> low = Sets.newHashSet();
-
-        srManager.routeService.getRouteTables().stream()
-                .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
-                .flatMap(Collection::stream)
-                .forEach(resolvedRoute -> {
-                    // Continue if next hop is not what we are looking for
-                    if (!Objects.equals(hostId.mac(), resolvedRoute.nextHopMac()) ||
-                            !Objects.equals(hostId.vlanId(), resolvedRoute.nextHopVlan())) {
-                        return;
-                    }
-                    // Prioritize STATIC and FPM among others
-                    if (resolvedRoute.route().source() == Route.Source.STATIC ||
-                            resolvedRoute.route().source() == Route.Source.FPM) {
-                        high.add(resolvedRoute.prefix());
-                    } else {
-                        low.add(resolvedRoute.prefix());
-                    }
-                });
-        return Stream.of(high, low).filter(set -> !set.isEmpty()).collect(Collectors.toList());
-    }
-
-    /**
-     * Returns batches of all subnets reachable on the given device.
-     * <p>
-     * First batch includes configured subnets, FPM and STATIC routes
-     * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
-     *
-     * @param deviceId device identifier
-     * @return list of subnet batches, each batch includes a set of prefixes.
-     */
-    // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
-    public List<Set<IpPrefix>> getBatchedSubnets(DeviceId deviceId) {
-        Set<IpPrefix> high = Sets.newHashSet();
-        Set<IpPrefix> low = Sets.newHashSet();
-
-        high.addAll(getConfiguredSubnets(deviceId));
-        srManager.routeService.getRouteTables().stream()
-                .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
-                .flatMap(Collection::stream)
-                .forEach(resolvedRoute -> {
-                    // Continue to next resolved route if none of the next hop attaches to given device
-                    if (srManager.nextHopLocations(resolvedRoute).stream()
-                            .noneMatch(cp -> Objects.equals(deviceId, cp.deviceId()))) {
-                        return;
-                    }
-                    // Prioritize STATIC and FPM among others
-                    if (resolvedRoute.route().source() == Route.Source.STATIC ||
-                            resolvedRoute.route().source() == Route.Source.FPM) {
-                        high.add(resolvedRoute.prefix());
-                    } else {
-                        low.add(resolvedRoute.prefix());
-                    }
-                });
-        return Lists.newArrayList(high, low);
-    }
-
-    /**
-     * Returns the subnet configuration of given device and port.
-     *
-     * @param deviceId Device ID
-     * @param port Port number
-     * @return The subnets configured on given port or empty set if
-     *         the port is unconfigured or suppressed.
-     */
-    public Set<IpPrefix> getPortSubnets(DeviceId deviceId, PortNumber port) {
-        ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
-
-        if (isSuppressedPort(connectPoint)) {
-            return Collections.emptySet();
-        }
-
-        Set<IpPrefix> subnets = srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
-                .flatMap(intf -> intf.ipAddressesList().stream())
-                .map(InterfaceIpAddress::subnetAddress)
-                .collect(Collectors.toSet());
-
-        if (subnets.isEmpty()) {
-            log.debug(NO_SUBNET, connectPoint);
-            return Collections.emptySet();
-        }
-        return subnets;
-    }
-
-    /**
-     * Returns all ports that has a subnet that contains any of the given IP addresses.
-     *
-     * @param ips a set of IP addresses
-     * @return a set of connect point that has a subnet that contains any of the given IP addresses
-     */
-    public Set<ConnectPoint> getPortByIps(Set<IpAddress> ips) {
-        return srManager.interfaceService.getInterfaces().stream()
-                .filter(intf -> intf.ipAddressesList().stream().anyMatch(intfAddress ->
-                            ips.stream().anyMatch(ip -> intfAddress.subnetAddress().contains(ip))))
-                .map(Interface::connectPoint)
-                .collect(Collectors.toSet());
-    }
-
-    /**
-     * Returns all the connect points of the segment routers that have the
-     * specified ip address in their subnets.
-     *
-     * @param destIpAddress target ip address
-     * @return connect points of the segment routers
-     */
-    public Set<ConnectPoint> getConnectPointsForASubnetHost(IpAddress destIpAddress) {
-        return srManager.interfaceService.getMatchingInterfaces(destIpAddress).stream()
-                .map(Interface::connectPoint)
-                .collect(Collectors.toSet());
-    }
-
-    /**
-     * Returns the router ip address of segment router that has the
-     * specified ip address in its subnets.
-     *
-     * @param destIpAddress target ip address
-     * @return router ip address
-     */
-    public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
-        Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
-
-        if (matchIntf == null) {
-            log.debug("No router was found for {}", destIpAddress);
-            return null;
-        }
-
-        DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
-        SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
-        if (srInfo == null) {
-            log.debug("No device config was found for {}", routerDeviceId);
-            return null;
-        }
-
-        return srInfo.ipv4Loopback;
-    }
-
-    /**
-     * Returns the router ipv6 address of segment router that has the
-     * specified ip address in its subnets.
-     *
-     * @param destIpAddress target ip address
-     * @return router ip address
-     */
-    public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
-        Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
-
-        if (matchIntf == null) {
-            log.debug("No router was found for {}", destIpAddress);
-            return null;
-        }
-
-        DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
-        SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
-        if (srInfo == null) {
-            log.debug("No device config was found for {}", routerDeviceId);
-            return null;
-        }
-
-        return srInfo.ipv6Loopback;
-    }
-
-    /**
-     * Returns the router mac address of segment router that has the
-     * specified ip address as one of its subnet gateway ip address.
-     *
-     * @param gatewayIpAddress router gateway ip address
-     * @return router mac address or null if not found
-     */
-    public MacAddress getRouterMacForAGatewayIp(IpAddress gatewayIpAddress) {
-        for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
-                deviceConfigMap.entrySet()) {
-            if (entry.getValue().gatewayIps.
-                    values().contains(gatewayIpAddress)) {
-                return entry.getValue().mac;
-            }
-        }
-
-        log.debug("Cannot find a router for {}", gatewayIpAddress);
-        return null;
-    }
-
-    /**
-     * Checks if the host IP is in any of the subnet defined in the router with the
-     * device ID given.
-     *
-     * @param deviceId device identification of the router
-     * @param hostIp   host IP address to check
-     * @return true if the given IP is within any of the subnet defined in the router,
-     * false if no subnet is defined in the router or if the host is not
-     * within any subnet defined in the router
-     */
-    public boolean inSameSubnet(DeviceId deviceId, IpAddress hostIp) {
-        Set<IpPrefix> subnets = getConfiguredSubnets(deviceId);
-        if (subnets == null) {
-            return false;
-        }
-
-        for (IpPrefix subnet: subnets) {
-            // Exclude /0 since it is a special case used for default route
-            if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Checks if the IP is in the subnet defined on given connect point.
-     *
-     * @param connectPoint Connect point
-     * @param ip The IP address to check
-     * @return True if the IP belongs to the subnet.
-     *         False if the IP does not belong to the subnet, or
-     *         there is no subnet configuration on given connect point.
-     */
-    public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
-        return getPortSubnets(connectPoint.deviceId(), connectPoint.port()).stream()
-                .anyMatch(ipPrefix -> ipPrefix.contains(ip));
-    }
-
-    /**
-     * Returns the ports corresponding to the adjacency Sid given.
-     *
-     * @param deviceId device identification of the router
-     * @param sid adjacency Sid
-     * @return set of port numbers
-     */
-    public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        return srinfo != null ?
-                ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
-                ImmutableSet.copyOf(new HashSet<>());
-    }
-
-    /**
-     * Check if the Sid given is whether adjacency Sid of the router device or not.
-     *
-     * @param deviceId device identification of the router
-     * @param sid Sid to check
-     * @return true if the Sid given is the adjacency Sid of the device,
-     * otherwise false
-     */
-    public boolean isAdjacencySid(DeviceId deviceId, int sid) {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        return srinfo != null && srinfo.adjacencySids.containsKey(sid);
-    }
-
-    /**
-     * Add subnet to specific connect point.
-     *
-     * @param cp connect point
-     * @param ipPrefix subnet being added to the device
-     */
-    public void addSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
-        checkNotNull(cp);
-        checkNotNull(ipPrefix);
-        SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
-        if (srinfo == null) {
-            log.warn("Device {} is not configured. Abort.", cp.deviceId());
-            return;
-        }
-        srinfo.subnets.put(cp.port(), ipPrefix);
-    }
-
-    /**
-     * Remove subnet from specific connect point.
-     *
-     * @param cp connect point
-     * @param ipPrefix subnet being removed to the device
-     */
-    public void removeSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
-        checkNotNull(cp);
-        checkNotNull(ipPrefix);
-        SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
-        if (srinfo == null) {
-            log.warn("Device {} is not configured. Abort.", cp.deviceId());
-            return;
-        }
-        srinfo.subnets.remove(cp.port(), ipPrefix);
-    }
-
-    private boolean isSuppressedPort(ConnectPoint connectPoint) {
-        SegmentRoutingAppConfig appConfig = srManager.cfgService
-                .getConfig(srManager.appId(), SegmentRoutingAppConfig.class);
-        if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
-            log.info("Interface configuration on port {} is ignored", connectPoint);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean isPairedEdge(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        if (!isEdgeDevice(deviceId)) {
-            return false;
-        }
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        return (srinfo.pairDeviceId == null) ? false : true;
-    }
-
-    public DeviceId getPairDeviceId(DeviceId deviceId) throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            return srinfo.pairDeviceId;
-        } else {
-            String message = "getPairDeviceId fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    public PortNumber getPairLocalPort(DeviceId deviceId)
-            throws DeviceConfigNotFoundException {
-        SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
-        if (srinfo != null) {
-            return srinfo.pairLocalPort;
-        } else {
-            String message = "getPairLocalPort fails for device: " + deviceId + ".";
-            throw new DeviceConfigNotFoundException(message);
-        }
-    }
-
-    public boolean isPairLocalPort(DeviceId devId, PortNumber pnum) {
-        return pnum.equals(srManager.getPairLocalPort(devId).orElse(null));
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
deleted file mode 100644
index 2d0bbd2..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.config;
-
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Mechanism through which group handler module retrieves
- * the device specific attributes such as segment ID,
- * Mac address...etc from group handler applications.
- */
-public interface DeviceProperties {
-    /**
-     * Checks if the device is configured.
-     *
-     * @param deviceId device identifier
-     * @return true if the device is configured
-     */
-    boolean isConfigured(DeviceId deviceId);
-
-    /**
-     * Returns the IPv4 segment id of a device to be used in group creation.
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return segment id of a device
-     */
-    int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
-    /**
-     * Returns the IPv6 segment id of a device to be used in group creation.
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return segment id of a device
-     */
-    int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
-    /**
-     * Returns the Mac address of a device to be used in group creation.
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return mac address of a device
-     */
-    MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
-    /**
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return the pseudowire routing label for a leaf node
-     */
-    int getPWRoutingLabel(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
-    /**
-     * Returns the router ipv4 address of a segment router.
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return router ip address
-     */
-    IpAddress getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
-    /**
-     * Returns the router ipv6 address of a segment router.
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return router ip address
-     */
-    IpAddress getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
-    /**
-     * Indicates whether a device is edge device or transit/core device.
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return boolean
-     */
-    boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
-    /**
-     * Returns all segment IDs to be considered in building auto
-     *
-     * created groups.
-     * @return list of segment IDs
-     */
-    List<Integer> getAllDeviceSegmentIds();
-
-    /**
-     * Returns subnet-to-ports mapping of given device.
-     *
-     * For each entry of the map
-     * Key: a subnet
-     * Value: a list of ports, which are bound to the subnet
-     *
-     * @param deviceId device identifier
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return a map that contains all subnet-to-ports mapping of given device
-     */
-    Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
-            throws DeviceConfigNotFoundException;
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
deleted file mode 100644
index de6ffb9..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright 2016-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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.config.Config;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * App configuration object for Segment Routing.
- */
-public class SegmentRoutingAppConfig extends Config<ApplicationId> {
-
-    private static Logger log = LoggerFactory.getLogger(SegmentRoutingAppConfig.class);
-
-    private static final String VROUTER_MACS = "vRouterMacs";
-    private static final String SUPPRESS_SUBNET = "suppressSubnet";
-    private static final String SUPPRESS_HOST_BY_PORT = "suppressHostByPort";
-    // TODO We might want to move SUPPRESS_HOST_BY_PROVIDER to Component Config
-    private static final String SUPPRESS_HOST_BY_PROVIDER = "suppressHostByProvider";
-    private static final String MPLS_ECMP = "MPLS-ECMP";
-    private static final String BLACKHOLE_IPS = "blackholeIps";
-
-    @Override
-    public boolean isValid() {
-        return hasOnlyFields(VROUTER_MACS, SUPPRESS_SUBNET,
-                SUPPRESS_HOST_BY_PORT, SUPPRESS_HOST_BY_PROVIDER, MPLS_ECMP, BLACKHOLE_IPS) &&
-                vRouterMacs() != null &&
-                suppressSubnet() != null && suppressHostByPort() != null &&
-                suppressHostByProvider() != null &&
-                blackholeIPs() != null;
-    }
-
-    /**
-     * Gets ips to blackhole from the config.
-     *
-     * @return Set of ips to blackhole, empty is not specified,
-     * or null if not valid
-     */
-    public Set<IpPrefix> blackholeIPs() {
-        if (!object.has(BLACKHOLE_IPS)) {
-            return ImmutableSet.of();
-        }
-
-        ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
-        ArrayNode arrayNode = (ArrayNode) object.path(BLACKHOLE_IPS);
-        for (JsonNode jsonNode : arrayNode) {
-            IpPrefix address;
-
-            String addrStr = jsonNode.asText(null);
-            if (addrStr != null) {
-                try {
-                    address = IpPrefix.valueOf(addrStr);
-                    builder.add(address);
-                } catch (IllegalArgumentException e) {
-                    log.debug("Not adding {}", jsonNode, e);
-                }
-            }
-        }
-        return builder.build();
-    }
-
-    /**
-     * Sets ips to blackhole to the config.
-     *
-     * @param blackholeIps a set of ips to blackhole
-     * @return this {@link SegmentRoutingAppConfig}
-     */
-    public SegmentRoutingAppConfig setBalckholeIps(Set<IpPrefix> blackholeIps) {
-        if (blackholeIps == null) {
-            object.remove(BLACKHOLE_IPS);
-        } else {
-            ArrayNode arrayNode = mapper.createArrayNode();
-
-            blackholeIps.forEach(ip -> {
-                arrayNode.add(ip.toString());
-            });
-
-            object.set(BLACKHOLE_IPS, arrayNode);
-        }
-        return this;
-    }
-
-    /**
-     * Gets MPLS-ECMP configuration from the config.
-     *
-     * @return the configuration of MPLS-ECMP. If it is not
-     *         specified, the default behavior is false.
-     */
-    public boolean mplsEcmp() {
-        return get(MPLS_ECMP, false);
-    }
-
-    /**
-     * Sets MPLS-ECMP to the config.
-     *
-     * @param mplsEcmp the MPLS-ECMP configuration
-     * @return this {@link SegmentRoutingAppConfig}
-     */
-    public SegmentRoutingAppConfig setMplsEcmp(boolean mplsEcmp) {
-        object.put(MPLS_ECMP, mplsEcmp);
-        return this;
-    }
-
-    /**
-     * Gets vRouters from the config.
-     *
-     * @return Set of vRouter MAC addresses, empty is not specified,
-     *         or null if not valid
-     */
-    public Set<MacAddress> vRouterMacs() {
-        if (!object.has(VROUTER_MACS)) {
-            return ImmutableSet.of();
-        }
-
-        ImmutableSet.Builder<MacAddress> builder = ImmutableSet.builder();
-        ArrayNode arrayNode = (ArrayNode) object.path(VROUTER_MACS);
-        for (JsonNode jsonNode : arrayNode) {
-            MacAddress mac;
-
-            String macStr = jsonNode.asText(null);
-            if (macStr == null) {
-                return null;
-            }
-            try {
-                mac = MacAddress.valueOf(macStr);
-            } catch (IllegalArgumentException e) {
-                return null;
-            }
-
-            builder.add(mac);
-        }
-        return builder.build();
-    }
-
-    /**
-     * Sets vRouters to the config.
-     *
-     * @param vRouterMacs a set of vRouter MAC addresses
-     * @return this {@link SegmentRoutingAppConfig}
-     */
-    public SegmentRoutingAppConfig setVRouterMacs(Set<MacAddress> vRouterMacs) {
-        if (vRouterMacs == null) {
-            object.remove(VROUTER_MACS);
-        } else {
-            ArrayNode arrayNode = mapper.createArrayNode();
-
-            vRouterMacs.forEach(mac -> {
-                arrayNode.add(mac.toString());
-            });
-
-            object.set(VROUTER_MACS, arrayNode);
-        }
-        return this;
-    }
-
-    /**
-     * Gets names of ports to which SegmentRouting does not push subnet rules.
-     *
-     * @return Set of port names, empty if not specified, or null
-     *         if not valid
-     */
-    public Set<ConnectPoint> suppressSubnet() {
-        if (!object.has(SUPPRESS_SUBNET)) {
-            return ImmutableSet.of();
-        }
-
-        ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
-        ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_SUBNET);
-        for (JsonNode jsonNode : arrayNode) {
-            String portName = jsonNode.asText(null);
-            if (portName == null) {
-                return null;
-            }
-            try {
-                builder.add(ConnectPoint.deviceConnectPoint(portName));
-            } catch (IllegalArgumentException e) {
-                return null;
-            }
-        }
-        return builder.build();
-    }
-
-    /**
-     * Sets names of ports to which SegmentRouting does not push subnet rules.
-     *
-     * @param suppressSubnet names of ports to which SegmentRouting does not push
-     *                     subnet rules
-     * @return this {@link SegmentRoutingAppConfig}
-     */
-    public SegmentRoutingAppConfig setSuppressSubnet(Set<ConnectPoint> suppressSubnet) {
-        if (suppressSubnet == null) {
-            object.remove(SUPPRESS_SUBNET);
-        } else {
-            ArrayNode arrayNode = mapper.createArrayNode();
-            suppressSubnet.forEach(connectPoint -> {
-                arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
-            });
-            object.set(SUPPRESS_SUBNET, arrayNode);
-        }
-        return this;
-    }
-
-    /**
-     * Gets connect points to which SegmentRouting does not push host rules.
-     *
-     * @return Set of connect points, empty if not specified, or null
-     *         if not valid
-     */
-    public Set<ConnectPoint> suppressHostByPort() {
-        if (!object.has(SUPPRESS_HOST_BY_PORT)) {
-            return ImmutableSet.of();
-        }
-
-        ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
-        ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PORT);
-        for (JsonNode jsonNode : arrayNode) {
-            String portName = jsonNode.asText(null);
-            if (portName == null) {
-                return null;
-            }
-            try {
-                builder.add(ConnectPoint.deviceConnectPoint(portName));
-            } catch (IllegalArgumentException e) {
-                return null;
-            }
-        }
-        return builder.build();
-    }
-
-    /**
-     * Sets connect points to which SegmentRouting does not push host rules.
-     *
-     * @param connectPoints connect points to which SegmentRouting does not push
-     *                     host rules
-     * @return this {@link SegmentRoutingAppConfig}
-     */
-    public SegmentRoutingAppConfig setSuppressHostByPort(Set<ConnectPoint> connectPoints) {
-        if (connectPoints == null) {
-            object.remove(SUPPRESS_HOST_BY_PORT);
-        } else {
-            ArrayNode arrayNode = mapper.createArrayNode();
-            connectPoints.forEach(connectPoint -> {
-                arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
-            });
-            object.set(SUPPRESS_HOST_BY_PORT, arrayNode);
-        }
-        return this;
-    }
-
-    /**
-     * Gets provider names from which SegmentRouting does not learn host info.
-     *
-     * @return array of provider names that need to be ignored
-     */
-    public Set<String> suppressHostByProvider() {
-        if (!object.has(SUPPRESS_HOST_BY_PROVIDER)) {
-            return ImmutableSet.of();
-        }
-
-        ImmutableSet.Builder<String> builder = ImmutableSet.builder();
-        ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PROVIDER);
-        for (JsonNode jsonNode : arrayNode) {
-            String providerName = jsonNode.asText(null);
-            if (providerName == null) {
-                return null;
-            }
-            builder.add(providerName);
-        }
-        return builder.build();
-    }
-
-    /**
-     * Sets provider names from which SegmentRouting does not learn host info.
-     *
-     * @param providers set of provider names
-     * @return this {@link SegmentRoutingAppConfig}
-     */
-    public SegmentRoutingAppConfig setSuppressHostByProvider(Set<String> providers) {
-        if (providers == null) {
-            object.remove(SUPPRESS_HOST_BY_PROVIDER);
-        } else {
-            ArrayNode arrayNode = mapper.createArrayNode();
-            providers.forEach(arrayNode::add);
-            object.set(SUPPRESS_HOST_BY_PROVIDER, arrayNode);
-        }
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(this)
-                .add("vRouterMacs", vRouterMacs())
-                .add("suppressSubnet", suppressSubnet())
-                .add("suppressHostByPort", suppressHostByPort())
-                .add("suppressHostByProvider", suppressHostByProvider())
-                .add("mplsEcmp", mplsEcmp())
-                .add("blackholeIps", blackholeIPs())
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
deleted file mode 100644
index 7959df6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright 2016-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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableMap;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * Configuration object for Segment Routing Application.
- */
-public class SegmentRoutingDeviceConfig extends Config<DeviceId> {
-    private static final String NAME = "name";
-    private static final String IP4 = "ipv4Loopback";
-    private static final String IP6 = "ipv6Loopback";
-    private static final String MAC = "routerMac";
-    private static final String IP4_SID = "ipv4NodeSid";
-    private static final String IP6_SID = "ipv6NodeSid";
-    private static final String EDGE = "isEdgeRouter";
-    /**
-     * Adjancency SIDs config.
-     *
-     * @deprecated in Loon (1.11). We are not using and do not plan to use it.
-     */
-    @Deprecated
-    private static final String ADJSIDS = "adjacencySids";
-
-    /**
-     * Adjancency SID config.
-     *
-     * @deprecated in Loon (1.11). We are not using and do not plan to use it.
-     */
-    @Deprecated
-    private static final String ADJSID = "adjSid";
-
-    /**
-     * Adjancency port config.
-     *
-     * @deprecated in Loon (1.11). We are not using and do not plan to use it.
-     */
-    @Deprecated
-    private static final String PORTS = "ports";
-
-    private static final String PAIR_DEVICE_ID = "pairDeviceId";
-    private static final String PAIR_LOCAL_PORT = "pairLocalPort";
-
-    @Override
-    public boolean isValid() {
-        return hasOnlyFields(NAME, IP4, IP6, MAC, IP4_SID, IP6_SID, EDGE, ADJSIDS, ADJSID, PORTS,
-                             PAIR_DEVICE_ID, PAIR_LOCAL_PORT) &&
-                name() != null &&
-                routerIpv4() != null && (!hasField(IP6) || routerIpv6() != null) &&
-                routerMac() != null &&
-                nodeSidIPv4() != -1 && (!hasField(IP6_SID) || nodeSidIPv6() != -1) &&
-                isEdgeRouter() != null &&
-                adjacencySids() != null &&
-                // pairDeviceId and pairLocalPort must be both configured or both omitted
-                (hasField(PAIR_DEVICE_ID) == hasField(PAIR_LOCAL_PORT)) &&
-                (!hasField(PAIR_DEVICE_ID) || pairDeviceId() != null) &&
-                (!hasField(PAIR_LOCAL_PORT) || pairLocalPort() != null);
-    }
-
-    /**
-     * Gets the name of the router.
-     *
-     * @return Optional name of the router. May be empty if not configured.
-     */
-    public Optional<String> name() {
-        String name = get(NAME, null);
-        return name != null ? Optional.of(name) : Optional.empty();
-    }
-
-    /**
-     * Sets the name of the router.
-     *
-     * @param name name of the router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setName(String name) {
-        return (SegmentRoutingDeviceConfig) setOrClear(NAME, name);
-    }
-
-    /**
-     * Gets the IPv4 address of the router.
-     *
-     * @return IP address of the router. Or null if not configured.
-     */
-    public Ip4Address routerIpv4() {
-        String ip = get(IP4, null);
-        return ip != null ? Ip4Address.valueOf(ip) : null;
-    }
-
-    /**
-     * Gets the IPv6 address of the router.
-     *
-     * @return IP address of the router. Or null if not configured.
-     */
-    public Ip6Address routerIpv6() {
-        String ip = get(IP6, null);
-        return ip != null ? Ip6Address.valueOf(ip) : null;
-    }
-
-    /**
-     * Sets the IPv4 address of the router.
-     *
-     * @param ip IPv4 address of the router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setRouterIpv4(String ip) {
-        return (SegmentRoutingDeviceConfig) setOrClear(IP4, ip);
-    }
-
-    /**
-     * Sets the IPv6 address of the router.
-     *
-     * @param ip IPv6 address of the router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setRouterIpv6(String ip) {
-        return (SegmentRoutingDeviceConfig) setOrClear(IP6, ip);
-    }
-
-    /**
-     * Gets the MAC address of the router.
-     *
-     * @return MAC address of the router. Or null if not configured.
-     */
-    public MacAddress routerMac() {
-        String mac = get(MAC, null);
-        return mac != null ? MacAddress.valueOf(mac) : null;
-    }
-
-    /**
-     * Sets the MAC address of the router.
-     *
-     * @param mac MAC address of the router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setRouterMac(String mac) {
-        return (SegmentRoutingDeviceConfig) setOrClear(MAC, mac);
-    }
-
-    /**
-     * Gets the IPv4 node SID of the router.
-     *
-     * @return node SID of the router. Or -1 if not configured.
-     */
-    public int nodeSidIPv4() {
-        return get(IP4_SID, -1);
-    }
-
-    /**
-     * Gets the IPv6 node SID of the router.
-     *
-     * @return node SID of the router. Or -1 if not configured.
-     */
-    public int nodeSidIPv6() {
-        return get(IP6_SID, -1);
-    }
-
-    /**
-     * Sets the node IPv4 node SID of the router.
-     *
-     * @param sid node SID of the router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setNodeSidIPv4(int sid) {
-        return (SegmentRoutingDeviceConfig) setOrClear(IP4_SID, sid);
-    }
-
-    /**
-     * Sets the node IPv6 node SID of the router.
-     *
-     * @param sid node SID of the router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setNodeSidIPv6(int sid) {
-        return (SegmentRoutingDeviceConfig) setOrClear(IP6_SID, sid);
-    }
-
-    /**
-     * Checks if the router is an edge router.
-     *
-     * @return true if the router is an edge router.
-     *         false if the router is not an edge router.
-     *         null if the value is not configured.
-     */
-    public Boolean isEdgeRouter() {
-        String isEdgeRouter = get(EDGE, null);
-        return isEdgeRouter != null ?
-                Boolean.valueOf(isEdgeRouter) :
-                null;
-    }
-
-    /**
-     * Specifies if the router is an edge router.
-     *
-     * @param isEdgeRouter true if the router is an edge router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setIsEdgeRouter(boolean isEdgeRouter) {
-        return (SegmentRoutingDeviceConfig) setOrClear(EDGE, isEdgeRouter);
-    }
-
-    /**
-     * Gets the adjacency SIDs of the router.
-     *
-     * @return adjacency SIDs of the router. Or null if not configured.
-     */
-    public Map<Integer, Set<Integer>> adjacencySids() {
-        if (!object.has(ADJSIDS)) {
-            return null;
-        }
-
-        Map<Integer, Set<Integer>> adjacencySids = new HashMap<>();
-        ArrayNode adjacencySidsNode = (ArrayNode) object.path(ADJSIDS);
-        for (JsonNode adjacencySidNode : adjacencySidsNode) {
-            int asid = adjacencySidNode.path(ADJSID).asInt(-1);
-            if (asid == -1) {
-                return null;
-            }
-
-            HashSet<Integer> ports = new HashSet<>();
-            ArrayNode portsNode = (ArrayNode) adjacencySidNode.path(PORTS);
-            for (JsonNode portNode : portsNode) {
-                int port = portNode.asInt(-1);
-                if (port == -1) {
-                    return null;
-                }
-                ports.add(port);
-            }
-            adjacencySids.put(asid, ports);
-        }
-
-        return ImmutableMap.copyOf(adjacencySids);
-    }
-
-    /**
-     * Sets the adjacency SIDs of the router.
-     *
-     * @param adjacencySids adjacency SIDs of the router.
-     * @return the config of the router.
-     */
-    public SegmentRoutingDeviceConfig setAdjacencySids(Map<Integer, Set<Integer>> adjacencySids) {
-        if (adjacencySids == null) {
-            object.remove(ADJSIDS);
-        } else {
-            ArrayNode adjacencySidsNode = mapper.createArrayNode();
-
-            adjacencySids.forEach((sid, ports) -> {
-                ObjectNode adjacencySidNode = mapper.createObjectNode();
-
-                adjacencySidNode.put(ADJSID, sid);
-
-                ArrayNode portsNode = mapper.createArrayNode();
-                ports.forEach(port -> {
-                    portsNode.add(port.toString());
-                });
-                adjacencySidNode.set(PORTS, portsNode);
-
-                adjacencySidsNode.add(adjacencySidNode);
-            });
-
-            object.set(ADJSIDS, adjacencySidsNode);
-        }
-
-        return this;
-    }
-
-    /**
-     * Gets the pair device id.
-     *
-     * @return pair device id; Or null if not configured.
-     */
-    public DeviceId pairDeviceId() {
-        String pairDeviceId = get(PAIR_DEVICE_ID, null);
-        return pairDeviceId != null ? DeviceId.deviceId(pairDeviceId) : null;
-    }
-
-    /**
-     * Sets the pair device id.
-     *
-     * @param deviceId pair device id
-     * @return this configuration
-     */
-    public SegmentRoutingDeviceConfig setPairDeviceId(DeviceId deviceId) {
-        return (SegmentRoutingDeviceConfig) setOrClear(PAIR_DEVICE_ID, deviceId.toString());
-    }
-
-    /**
-     * Gets the pair local port.
-     *
-     * @return pair local port; Or null if not configured.
-     */
-    public PortNumber pairLocalPort() {
-        long pairLocalPort = get(PAIR_LOCAL_PORT, -1L);
-        return pairLocalPort != -1L ? PortNumber.portNumber(pairLocalPort) : null;
-    }
-
-    /**
-     * Sets the pair local port.
-     *
-     * @param portNumber pair local port
-     * @return this configuration
-     */
-    public SegmentRoutingDeviceConfig setPairLocalPort(PortNumber portNumber) {
-        return (SegmentRoutingDeviceConfig) setOrClear(PAIR_LOCAL_PORT, portNumber.toLong());
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/package-info.java
deleted file mode 100644
index a664a8f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Segment routing network configuration mechanism.
- */
-package org.onosproject.segmentrouting.config;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
deleted file mode 100644
index f8d3053..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ /dev/null
@@ -1,1794 +0,0 @@
-/*
- * 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.grouphandler;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import org.apache.commons.lang3.RandomUtils;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.segmentrouting.DefaultRoutingHandler;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceProperties;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.slf4j.Logger;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Default ECMP group handler creation module. This component creates a set of
- * ECMP groups for every neighbor that this device is connected to based on
- * whether the current device is an edge device or a transit device.
- */
-public class DefaultGroupHandler {
-    private static final Logger log = getLogger(DefaultGroupHandler.class);
-
-    private static final long VERIFY_INTERVAL = 30; // secs
-
-    protected final DeviceId deviceId;
-    protected final ApplicationId appId;
-    protected final DeviceProperties deviceConfig;
-    protected final List<Integer> allSegmentIds;
-    protected int ipv4NodeSegmentId = -1;
-    protected int ipv6NodeSegmentId = -1;
-    protected boolean isEdgeRouter = false;
-    protected MacAddress nodeMacAddr = null;
-    protected LinkService linkService;
-    protected FlowObjectiveService flowObjectiveService;
-    private DeviceConfiguration config;
-
-    /**
-     * local store for neighbor-device-ids and the set of ports on this device
-     * that connect to the same neighbor.
-     */
-    protected ConcurrentHashMap<DeviceId, Set<PortNumber>> devicePortMap =
-            new ConcurrentHashMap<>();
-    /**
-     *  local store for ports on this device connected to neighbor-device-id.
-     */
-    protected ConcurrentHashMap<PortNumber, DeviceId> portDeviceMap =
-            new ConcurrentHashMap<>();
-
-    // distributed store for (device+destination-set) mapped to next-id and neighbors
-    protected EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
-            dsNextObjStore = null;
-    // distributed store for (device+subnet-ip-prefix) mapped to next-id
-    protected EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
-            vlanNextObjStore = null;
-    // distributed store for (device+mac+vlan+treatment) mapped to next-id
-    protected EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer>
-            macVlanNextObjStore = null;
-    // distributed store for (device+port+treatment) mapped to next-id
-    protected EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
-            portNextObjStore = null;
-    private SegmentRoutingManager srManager;
-
-    private ScheduledExecutorService executorService
-    = newScheduledThreadPool(1, groupedThreads("bktCorrector", "bktC-%d", log));
-
-    protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
-            .register(URI.class).register(HashSet.class)
-            .register(DeviceId.class).register(PortNumber.class)
-            .register(DestinationSet.class).register(PolicyGroupIdentifier.class)
-            .register(PolicyGroupParams.class)
-            .register(GroupBucketIdentifier.class)
-            .register(GroupBucketIdentifier.BucketOutputType.class);
-
-    protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId,
-                                  DeviceProperties config,
-                                  LinkService linkService,
-                                  FlowObjectiveService flowObjService,
-                                  SegmentRoutingManager srManager) {
-        this.deviceId = checkNotNull(deviceId);
-        this.appId = checkNotNull(appId);
-        this.deviceConfig = checkNotNull(config);
-        this.linkService = checkNotNull(linkService);
-        this.allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
-        try {
-            this.ipv4NodeSegmentId = config.getIPv4SegmentId(deviceId);
-            this.ipv6NodeSegmentId = config.getIPv6SegmentId(deviceId);
-            this.isEdgeRouter = config.isEdgeDevice(deviceId);
-            this.nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage()
-                    + " Skipping value assignment in DefaultGroupHandler");
-        }
-        this.flowObjectiveService = flowObjService;
-        this.dsNextObjStore = srManager.dsNextObjStore();
-        this.vlanNextObjStore = srManager.vlanNextObjStore();
-        this.portNextObjStore = srManager.portNextObjStore();
-        this.macVlanNextObjStore = srManager.macVlanNextObjStore();
-        this.srManager = srManager;
-        executorService.scheduleWithFixedDelay(new BucketCorrector(), 10,
-                                               VERIFY_INTERVAL,
-                                               TimeUnit.SECONDS);
-        populateNeighborMaps();
-    }
-
-    /**
-     * Gracefully shuts down a groupHandler. Typically called when the handler is
-     * no longer needed.
-     */
-    public void shutdown() {
-        executorService.shutdown();
-    }
-
-    /**
-     * Creates a group handler object.
-     *
-     * @param deviceId device identifier
-     * @param appId application identifier
-     * @param config interface to retrieve the device properties
-     * @param linkService link service object
-     * @param flowObjService flow objective service object
-     * @param srManager segment routing manager
-     * @throws DeviceConfigNotFoundException if the device configuration is not found
-     * @return default group handler type
-     */
-    public static DefaultGroupHandler createGroupHandler(
-                                                         DeviceId deviceId,
-                                                         ApplicationId appId,
-                                                         DeviceProperties config,
-                                                         LinkService linkService,
-                                                         FlowObjectiveService flowObjService,
-                                                         SegmentRoutingManager srManager)
-                                                                 throws DeviceConfigNotFoundException {
-        return new DefaultGroupHandler(deviceId, appId, config,
-                                       linkService,
-                                       flowObjService,
-                                       srManager);
-    }
-
-    /**
-     * Updates local stores for link-src-device/port to neighbor (link-dst) for
-     * link that has come up.
-     *
-     * @param link the infrastructure link
-     */
-    public void portUpForLink(Link link) {
-        if (!link.src().deviceId().equals(deviceId)) {
-            log.warn("linkUp: deviceId{} doesn't match with link src {}",
-                     deviceId, link.src().deviceId());
-            return;
-        }
-
-        log.info("* portUpForLink: Device {} linkUp at local port {} to "
-                + "neighbor {}", deviceId, link.src().port(), link.dst().deviceId());
-        // ensure local state is updated even if linkup is aborted later on
-        addNeighborAtPort(link.dst().deviceId(),
-                          link.src().port());
-    }
-
-    /**
-     * Updates local stores for link-src-device/port to neighbor (link-dst) for
-     * link that has gone down.
-     *
-     * @param link the infrastructure link
-     */
-    public void portDownForLink(Link link) {
-        PortNumber port = link.src().port();
-        if (portDeviceMap.get(port) == null) {
-            log.warn("portDown: unknown port");
-            return;
-        }
-
-        log.debug("Device {} portDown {} to neighbor {}", deviceId, port,
-                  portDeviceMap.get(port));
-        devicePortMap.get(portDeviceMap.get(port)).remove(port);
-        portDeviceMap.remove(port);
-    }
-
-    /**
-     * Cleans up local stores for removed neighbor device.
-     *
-     * @param neighborId the device identifier for the neighbor device
-     */
-    public void cleanUpForNeighborDown(DeviceId neighborId) {
-        Set<PortNumber> ports = devicePortMap.remove(neighborId);
-        if (ports != null) {
-            ports.forEach(p -> portDeviceMap.remove(p));
-        }
-    }
-
-    /**
-     * Checks all groups in the src-device of link for neighbor sets that include
-     * the dst-device of link, and edits the hash groups according to link up
-     * or down. Should only be called by the master instance of the src-switch
-     * of link. Typically used when there are no route-path changes due to the
-     * link up or down, as the ECMPspg does not change.
-     *
-     * @param link the infrastructure link that has gone down or come up
-     * @param linkDown true if link has gone down
-     * @param firstTime true if link has come up for the first time i.e a link
-     *                  not seen-before
-     */
-    public void retryHash(Link link, boolean linkDown, boolean firstTime) {
-        MacAddress neighborMac;
-        try {
-            neighborMac = deviceConfig.getDeviceMac(link.dst().deviceId());
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " Aborting retryHash.");
-            return;
-        }
-        // find all the destinationSets related to link
-        Set<DestinationSetNextObjectiveStoreKey> dsKeySet = dsNextObjStore.entrySet()
-                .stream()
-                .filter(entry -> entry.getKey().deviceId().equals(deviceId))
-                // Filter out PW transit groups or include them if MPLS ECMP is supported
-                .filter(entry -> !entry.getKey().destinationSet().notBos() ||
-                        (entry.getKey().destinationSet().notBos() && srManager.getMplsEcmp()))
-                // Filter out simple SWAP groups or include them if MPLS ECMP is supported
-                .filter(entry -> !entry.getKey().destinationSet().swap() ||
-                        (entry.getKey().destinationSet().swap() && srManager.getMplsEcmp()))
-                .filter(entry -> entry.getValue().containsNextHop(link.dst().deviceId()))
-                .map(entry -> entry.getKey())
-                .collect(Collectors.toSet());
-
-        log.debug("retryHash: dsNextObjStore contents for linkSrc {} -> linkDst {}: {}",
-                  deviceId, link.dst().deviceId(), dsKeySet);
-
-        for (DestinationSetNextObjectiveStoreKey dsKey : dsKeySet) {
-            NextNeighbors nextHops = dsNextObjStore.get(dsKey);
-            if (nextHops == null) {
-                log.warn("retryHash in device {}, but global store has no record "
-                         + "for dsKey:{}", deviceId, dsKey);
-                continue;
-            }
-            int nextId = nextHops.nextId();
-            Set<DeviceId> dstSet = nextHops.getDstForNextHop(link.dst().deviceId());
-            if (!linkDown) {
-                List<PortLabel> pl = Lists.newArrayList();
-                if (firstTime) {
-                    // some links may have come up before the next-objective was created
-                    // we take this opportunity to ensure other ports to same next-hop-dst
-                    // are part of the hash group (see CORD-1180). Duplicate additions
-                    // to the same hash group are avoided by the driver.
-                    for (PortNumber p : devicePortMap.get(link.dst().deviceId())) {
-                        dstSet.forEach(dst -> {
-                            int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
-                            pl.add(new PortLabel(p, edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
-                        });
-                    }
-                    addToHashedNextObjective(pl, neighborMac, nextId);
-                } else {
-                    // handle only the port that came up
-                    dstSet.forEach(dst -> {
-                        int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
-                        pl.add(new PortLabel(link.src().port(), edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
-                    });
-                    addToHashedNextObjective(pl, neighborMac, nextId);
-                }
-            } else {
-                // linkdown
-                List<PortLabel> pl = Lists.newArrayList();
-                dstSet.forEach(dst -> {
-                    int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
-                    pl.add(new PortLabel(link.src().port(), edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
-                });
-                removeFromHashedNextObjective(pl, neighborMac, nextId);
-            }
-        }
-    }
-
-    /**
-     * Utility class for associating output ports and the corresponding MPLS
-     * labels to push. In dual-homing, there are different labels to push
-     * corresponding to the destination switches in an edge-pair. If both
-     * destinations are reachable via the same spine, then the output-port to
-     * the spine will be associated with two labels i.e. there will be two
-     * PortLabel objects for the same port but with different labels.
-     */
-    private class PortLabel {
-        PortNumber port;
-        int edgeLabel;
-        boolean popVlan;
-
-        PortLabel(PortNumber port, int edgeLabel, boolean popVlan) {
-            this.port = port;
-            this.edgeLabel = edgeLabel;
-            this.popVlan = popVlan;
-        }
-
-        @Override
-        public String toString() {
-            return port.toString() + "/" + String.valueOf(edgeLabel) + (popVlan ? "/popVlan" : "");
-        }
-    }
-
-    /**
-     * Makes a call to the FlowObjective service to add buckets to
-     * a hashed group. User must ensure that all the ports & labels are meant
-     * same neighbor (ie. dstMac).
-     *
-     * @param portLabels a collection of port & label combinations to add
-     *                   to the hash group identified by the nextId
-     * @param dstMac destination mac address of next-hop
-     * @param nextId id for next-objective to which buckets will be added
-     *
-     */
-    private void addToHashedNextObjective(Collection<PortLabel> portLabels,
-                                          MacAddress dstMac, Integer nextId) {
-        // setup metadata to pass to nextObjective - indicate the vlan on egress
-        // if needed by the switch pipeline. Since hashed next-hops are always to
-        // other neighboring routers, there is no subnet assigned on those ports.
-        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
-        metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
-                .withId(nextId)
-                .withType(NextObjective.Type.HASHED)
-                .withMeta(metabuilder.build())
-                .fromApp(appId);
-        // Create the new buckets to be updated
-        portLabels.forEach(pl -> {
-            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-            tBuilder.setOutput(pl.port)
-                .setEthDst(dstMac)
-                .setEthSrc(nodeMacAddr);
-            if (pl.popVlan) {
-                tBuilder.popVlan();
-            }
-            if (pl.edgeLabel != DestinationSet.NO_EDGE_LABEL) {
-                tBuilder.pushMpls()
-                    .copyTtlOut()
-                    .setMpls(MplsLabel.mplsLabel(pl.edgeLabel));
-            }
-            nextObjBuilder.addTreatment(tBuilder.build());
-        });
-
-        log.debug("addToHash in device {}: Adding Bucket with port/label {} "
-                + "to nextId {}", deviceId, portLabels, nextId);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("addToHash port/label {} addedTo "
-                        + "NextObj {} on {}", portLabels, nextId, deviceId),
-                (objective, error) -> {
-                    log.warn("addToHash failed to add port/label {} to NextObj {} on {}: {}",
-                            portLabels, nextId, deviceId, error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-        NextObjective nextObjective = nextObjBuilder.addToExisting(context);
-        flowObjectiveService.next(deviceId, nextObjective);
-    }
-
-    /**
-     * Makes a call to the FlowObjective service to remove buckets from
-     * a hash group. User must ensure that all the ports & labels are meant
-     * same neighbor (ie. dstMac).
-     *
-     * @param portLabels a collection of port & label combinations to remove
-     *                   from the hash group identified by the nextId
-     * @param dstMac destination mac address of next-hop
-     * @param nextId id for next-objective from which buckets will be removed
-     */
-    private void removeFromHashedNextObjective(Collection<PortLabel> portLabels,
-                                               MacAddress dstMac, Integer nextId) {
-        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
-        metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder()
-                .withType(NextObjective.Type.HASHED) //same as original
-                .withMeta(metabuilder.build())
-                .withId(nextId)
-                .fromApp(appId);
-        // Create the buckets to be removed
-        portLabels.forEach(pl -> {
-            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-            tBuilder.setOutput(pl.port)
-                .setEthDst(dstMac)
-                .setEthSrc(nodeMacAddr);
-            if (pl.popVlan) {
-                tBuilder.popVlan();
-            }
-            if (pl.edgeLabel != DestinationSet.NO_EDGE_LABEL) {
-                tBuilder.pushMpls()
-                    .copyTtlOut()
-                    .setMpls(MplsLabel.mplsLabel(pl.edgeLabel));
-            }
-            nextObjBuilder.addTreatment(tBuilder.build());
-        });
-        log.debug("removeFromHash in device {}: Removing Bucket with port/label"
-                + " {} from nextId {}", deviceId, portLabels, nextId);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("port/label {} removedFrom NextObj"
-                        + " {} on {}", portLabels, nextId, deviceId),
-                (objective, error) -> {
-                    log.warn("port/label {} failed to removeFrom NextObj {} on {}: {}",
-                            portLabels, nextId, deviceId, error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-        NextObjective nextObjective = nextObjBuilder.removeFromExisting(context);
-        flowObjectiveService.next(deviceId, nextObjective);
-    }
-
-    /**
-     * Checks all the hash-groups in the target-switch meant for the destination
-     * switch, and either adds or removes buckets to make the neighbor-set
-     * match the given next-hops. Typically called by the master instance of the
-     * destination switch, which may be different from the master instance of the
-     * target switch where hash-group changes are made.
-     *
-     * @param targetSw the switch in which the hash groups will be edited
-     * @param nextHops the current next hops for the target switch to reach
-     *                  the dest sw
-     * @param destSw  the destination switch
-     * @param revoke true if hash groups need to remove buckets from the
-     *                          the groups to match the current next hops
-     * @return true if calls are made to edit buckets, or if no edits are required
-     */
-    public boolean fixHashGroups(DeviceId targetSw, Set<DeviceId> nextHops,
-                                 DeviceId destSw, boolean revoke) {
-        // temporary storage of keys to be updated
-        Map<DestinationSetNextObjectiveStoreKey, Set<DeviceId>> tempStore =
-                new HashMap<>();
-        boolean foundNextObjective = false, success = true;
-
-        // retrieve hash-groups meant for destSw, which have destinationSets
-        // with different neighbors than the given next-hops
-        for (DestinationSetNextObjectiveStoreKey dskey : dsNextObjStore.keySet()) {
-            if (!dskey.deviceId().equals(targetSw) ||
-                    !dskey.destinationSet().getDestinationSwitches().contains(destSw)) {
-                continue;
-            }
-            foundNextObjective = true;
-            NextNeighbors nhops = dsNextObjStore.get(dskey);
-            Set<DeviceId> currNeighbors = nhops.nextHops(destSw);
-            int edgeLabel = dskey.destinationSet().getEdgeLabel(destSw);
-            Integer nextId = nhops.nextId();
-            if (currNeighbors == null || nextHops == null) {
-                log.warn("fixing hash groups but found currNeighbors:{} or nextHops:{}"
-                        + " in targetSw:{} for dstSw:{}", currNeighbors,
-                         nextHops, targetSw, destSw);
-                success &= false;
-                continue;
-            }
-
-            // some store elements may not be hashed next-objectives - ignore them
-            if (isSimpleNextObjective(dskey)) {
-                log.debug("Ignoring {} of SIMPLE nextObj for targetSw:{}"
-                        + " -> dstSw:{} with current nextHops:{} to new"
-                        + " nextHops: {} in nextId:{}",
-                          (revoke) ? "removal" : "addition", targetSw, destSw,
-                          currNeighbors, nextHops, nextId);
-                if ((revoke && !nextHops.isEmpty())
-                        || (!revoke && !nextHops.equals(currNeighbors))) {
-                    log.debug("Simple next objective cannot be edited to "
-                            + "move from {} to {}", currNeighbors, nextHops);
-                }
-                continue;
-            }
-
-            Set<DeviceId> diff;
-            if (revoke) {
-                diff = Sets.difference(currNeighbors, nextHops);
-                log.debug("targetSw:{} -> dstSw:{} in nextId:{} has current next "
-                        + "hops:{} ..removing {}", targetSw, destSw, nextId,
-                        currNeighbors, diff);
-            } else {
-                diff = Sets.difference(nextHops, currNeighbors);
-                log.debug("targetSw:{} -> dstSw:{} in nextId:{} has current next "
-                        + "hops:{} ..adding {}", targetSw, destSw, nextId,
-                        currNeighbors, diff);
-            }
-            boolean suc = updateAllPortsToNextHop(diff, edgeLabel, nextId, popVlanInHashGroup(dskey.destinationSet()),
-                                                  revoke);
-            if (suc) {
-                // to update neighbor set with changes made
-                if (revoke) {
-                    tempStore.put(dskey, Sets.difference(currNeighbors, diff));
-                } else {
-                    tempStore.put(dskey, Sets.union(currNeighbors, diff));
-                }
-            }
-            success &= suc;
-        }
-
-        if (!foundNextObjective) {
-            log.debug("Cannot find any nextObjectives for route targetSw:{} "
-                    + "-> dstSw:{}", targetSw, destSw);
-            return false; // nothing to do, return false so re-route will be performed
-        }
-
-        // update the dsNextObjectiveStore with new destinationSet to nextId mappings
-        for (DestinationSetNextObjectiveStoreKey key : tempStore.keySet()) {
-            NextNeighbors currentNextHops = dsNextObjStore.get(key);
-            if (currentNextHops == null) {
-                log.warn("fixHashGroups could not update global store in "
-                        + "device {} .. missing nextNeighbors for key {}",
-                        deviceId, key);
-                continue;
-            }
-            Set<DeviceId> newNeighbors = new HashSet<>();
-            newNeighbors.addAll(tempStore.get(key));
-            Map<DeviceId, Set<DeviceId>> oldDstNextHops =
-                    ImmutableMap.copyOf(currentNextHops.dstNextHops());
-            currentNextHops.dstNextHops().put(destSw, newNeighbors); //local change
-            log.debug("Updating nsNextObjStore target:{} -> dst:{} in key:{} nextId:{}",
-                      targetSw, destSw, key, currentNextHops.nextId());
-            log.debug("Old dstNextHops: {}", oldDstNextHops);
-            log.debug("New dstNextHops: {}", currentNextHops.dstNextHops());
-            // update global store
-            dsNextObjStore.put(key,
-                               new NextNeighbors(currentNextHops.dstNextHops(),
-                                                 currentNextHops.nextId()));
-        }
-
-        // even if one fails and others succeed, return false so ECMPspg not updated
-        return success;
-    }
-
-    /**
-     * Updates the DestinationSetNextObjectiveStore with any per-destination nexthops
-     * that are not already in the store for the given DestinationSet. Note that
-     * this method does not remove existing next hops for the destinations in the
-     * DestinationSet.
-     *
-     * @param ds the DestinationSet for which the next hops need to be updated
-     * @param newDstNextHops a map of per-destination next hops to update the
-     *                          destinationSet with
-     * @return true if successful in updating all next hops
-     */
-    private boolean updateNextHops(DestinationSet ds,
-                                  Map<DeviceId, Set<DeviceId>> newDstNextHops) {
-        DestinationSetNextObjectiveStoreKey key =
-                new DestinationSetNextObjectiveStoreKey(deviceId, ds);
-        NextNeighbors currNext = dsNextObjStore.get(key);
-        Map<DeviceId, Set<DeviceId>> currDstNextHops = currNext.dstNextHops();
-
-        // add newDstNextHops to currDstNextHops for each dst
-        boolean success = true;
-        for (DeviceId dstSw : ds.getDestinationSwitches()) {
-            Set<DeviceId> currNhops = currDstNextHops.get(dstSw);
-            Set<DeviceId> newNhops = newDstNextHops.get(dstSw);
-            currNhops = (currNhops == null) ? Sets.newHashSet() : currNhops;
-            newNhops = (newNhops == null) ? Sets.newHashSet() : newNhops;
-            int edgeLabel = ds.getEdgeLabel(dstSw);
-            int nextId = currNext.nextId();
-
-            // new next hops should be added
-            boolean suc = updateAllPortsToNextHop(Sets.difference(newNhops, currNhops),
-                                                  edgeLabel, nextId, popVlanInHashGroup(key.destinationSet()), false);
-            if (suc) {
-                currNhops.addAll(newNhops);
-                currDstNextHops.put(dstSw, currNhops); // this is only a local change
-            }
-            success &= suc;
-        }
-
-        if (success) {
-            // update global store
-            dsNextObjStore.put(key, new NextNeighbors(currDstNextHops,
-                                                      currNext.nextId()));
-            log.debug("Updated device:{} ds:{} new next-hops: {}", deviceId, ds,
-                      dsNextObjStore.get(key));
-        }
-        return success;
-    }
-
-    /**
-     * Adds or removes buckets for all ports to a set of neighbor devices. Caller
-     * needs to ensure that the  given neighbors are all next hops towards the
-     * same destination (represented by the given edgeLabel).
-     *
-     * @param neighbors set of neighbor device ids
-     * @param edgeLabel MPLS label to use in buckets
-     * @param nextId the nextObjective to change
-     * @param popVlan this hash group bucket shuold includes a popVlan action
-     * @param revoke true if buckets need to be removed, false if they need to
-     *          be added
-     * @return true if successful in adding or removing buckets for all ports
-     *                  to the neighbors
-     */
-    private boolean updateAllPortsToNextHop(Set<DeviceId> neighbors, int edgeLabel,
-                                         int nextId, boolean popVlan, boolean revoke) {
-        for (DeviceId neighbor : neighbors) {
-            MacAddress neighborMac;
-            try {
-                neighborMac = deviceConfig.getDeviceMac(neighbor);
-            } catch (DeviceConfigNotFoundException e) {
-                log.warn(e.getMessage() + " Aborting updateAllPortsToNextHop"
-                        + " for nextId:" + nextId);
-                return false;
-            }
-            Collection<PortNumber> portsToNeighbor = devicePortMap.get(neighbor);
-            if (portsToNeighbor == null || portsToNeighbor.isEmpty()) {
-                log.warn("No ports found in dev:{} for neighbor:{} .. cannot "
-                        + "updateAllPortsToNextHop for nextId: {}",
-                         deviceId, neighbor, nextId);
-                return false;
-            }
-            List<PortLabel> pl = Lists.newArrayList();
-            portsToNeighbor.forEach(p -> pl.add(new PortLabel(p, edgeLabel, popVlan)));
-            if (revoke) {
-                log.debug("updateAllPortsToNextHops in device {}: Removing Bucket(s) "
-                        + "with Port/Label:{} to next object id {}",
-                        deviceId, pl, nextId);
-                removeFromHashedNextObjective(pl, neighborMac, nextId);
-            } else {
-                log.debug("fixHashGroup in device {}: Adding Bucket(s) "
-                        + "with Port/Label: {} to next object id {}",
-                        deviceId, pl, nextId);
-                addToHashedNextObjective(pl, neighborMac, nextId);
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns true if the destination set is meant for swap or multi-labeled
-     * packet transport, and MPLS ECMP is not supported.
-     *
-     * @param dskey the key representing the destination set
-     * @return true if destination set is meant for simple next objectives
-     */
-    boolean isSimpleNextObjective(DestinationSetNextObjectiveStoreKey dskey) {
-        return (dskey.destinationSet().notBos() || dskey.destinationSet().swap())
-                && !srManager.getMplsEcmp();
-    }
-
-    /**
-     * Adds or removes a port that has been configured with a vlan to a broadcast group
-     * for bridging. Should only be called by the master instance for this device.
-     *
-     * @param port the port on this device that needs to be added/removed to a bcast group
-     * @param vlanId the vlan id corresponding to the broadcast domain/group
-     * @param popVlan indicates if packets should be sent out untagged or not out
-     *                of the port. If true, indicates an access (untagged) or native vlan
-     *                configuration. If false, indicates a trunk (tagged) vlan config.
-     * @param portUp true if port is enabled, false if disabled
-     */
-    public void processEdgePort(PortNumber port, VlanId vlanId,
-                                boolean popVlan, boolean portUp) {
-        //get the next id for the subnet and edit it.
-        Integer nextId = getVlanNextObjectiveId(vlanId);
-        if (nextId == -1) {
-            if (portUp) {
-                log.debug("**Creating flooding group for first port enabled in"
-                        + " vlan {} on dev {} port {}", vlanId, deviceId, port);
-                createBcastGroupFromVlan(vlanId, Collections.singleton(port));
-            } else {
-                log.warn("Could not find flooding group for subnet {} on dev:{} when"
-                        + " removing port:{}", vlanId, deviceId, port);
-            }
-            return;
-        }
-
-        log.info("**port{} in device {}: {} Bucket with Port {} to"
-                + " next-id {}", (portUp) ? "UP" : "DOWN", deviceId,
-                                          (portUp) ? "Adding" : "Removing",
-                                          port, nextId);
-        // Create the bucket to be added or removed
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        if (popVlan) {
-            tBuilder.popVlan();
-        }
-        tBuilder.setOutput(port);
-
-        TrafficSelector metadata =
-                DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.BROADCAST).fromApp(appId)
-                .addTreatment(tBuilder.build())
-                .withMeta(metadata);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-            (objective) -> log.debug("port {} successfully {} NextObj {} on {}",
-                                     port, (portUp) ? "addedTo" : "removedFrom",
-                                     nextId, deviceId),
-            (objective, error) -> {
-                log.warn("port {} failed to {} NextObj {} on {}: {}",
-                        port, (portUp) ? "addTo" : "removeFrom", nextId, deviceId, error);
-                srManager.invalidateNextObj(objective.id());
-            });
-
-        NextObjective nextObj = (portUp) ? nextObjBuilder.addToExisting(context)
-                                         : nextObjBuilder.removeFromExisting(context);
-        log.debug("edgePort processed: Submited next objective {} in device {}",
-                  nextId, deviceId);
-        flowObjectiveService.next(deviceId, nextObj);
-    }
-
-    /**
-     * Returns the next objective of type hashed (or simple) associated with the
-     * destination set. In addition, updates the existing next-objective if new
-     * route-paths found have resulted in the addition of new next-hops to a
-     * particular destination. If there is no existing next objective for this
-     * destination set, this method would create a next objective and return the
-     * nextId. Optionally metadata can be passed in for the creation of the next
-     * objective. If the parameter simple is true then a simple next objective
-     * is created instead of a hashed one.
-     *
-     * @param ds destination set
-     * @param nextHops a map of per destination next hops
-     * @param meta metadata passed into the creation of a Next Objective
-     * @param simple if true, a simple next objective will be created instead of
-     *            a hashed next objective
-     * @return int if found or -1 if there are errors in the creation of the
-     *         neighbor set.
-     */
-    public int getNextObjectiveId(DestinationSet ds,
-                                  Map<DeviceId, Set<DeviceId>> nextHops,
-                                  TrafficSelector meta, boolean simple) {
-        NextNeighbors next = dsNextObjStore.
-                get(new DestinationSetNextObjectiveStoreKey(deviceId, ds));
-        if (next == null) {
-            log.debug("getNextObjectiveId in device{}: Next objective id "
-                    + "not found for {} ... creating", deviceId, ds);
-            log.trace("getNextObjectiveId: nsNextObjStore contents for device {}: {}",
-                      deviceId,
-                      dsNextObjStore.entrySet()
-                      .stream()
-                      .filter((nsStoreEntry) ->
-                      (nsStoreEntry.getKey().deviceId().equals(deviceId)))
-                      .collect(Collectors.toList()));
-
-            createGroupFromDestinationSet(ds, nextHops, meta, simple);
-            next = dsNextObjStore.
-                    get(new DestinationSetNextObjectiveStoreKey(deviceId, ds));
-            if (next == null) {
-                log.warn("getNextObjectiveId: unable to create next objective");
-                // failure in creating group
-                return -1;
-            } else {
-                log.debug("getNextObjectiveId in device{}: Next objective id {} "
-                    + "created for {}", deviceId, next.nextId(), ds);
-            }
-        } else {
-            log.trace("getNextObjectiveId in device{}: Next objective id {} "
-                    + "found for {}", deviceId, next.nextId(), ds);
-            // should fix hash groups too if next-hops have changed
-            if (!next.dstNextHops().equals(nextHops)) {
-                log.debug("Nexthops have changed for dev:{} nextId:{} ..updating",
-                          deviceId, next.nextId());
-                if (!updateNextHops(ds, nextHops)) {
-                    // failure in updating group
-                    return -1;
-                }
-            }
-        }
-        return next.nextId();
-    }
-
-    /**
-     * Returns the next objective of type broadcast associated with the vlan,
-     * or -1 if no such objective exists. Note that this method does NOT create
-     * the next objective as a side-effect. It is expected that is objective is
-     * created at startup from network configuration. Typically this is used
-     * for L2 flooding within the subnet configured on the switch.
-     *
-     * @param vlanId vlan id
-     * @return int if found or -1
-     */
-    public int getVlanNextObjectiveId(VlanId vlanId) {
-        Integer nextId = vlanNextObjStore.
-                get(new VlanNextObjectiveStoreKey(deviceId, vlanId));
-
-        return (nextId != null) ? nextId : -1;
-    }
-
-    /**
-     * Returns the next objective of type simple associated with the mac/vlan on the
-     * device, given the treatment. Different treatments to the same mac/vlan result
-     * in different next objectives. If no such objective exists, this method
-     * creates one (if requested) and returns the id. Optionally metadata can be passed in for
-     * the creation of the objective. Typically this is used for L2 and L3 forwarding
-     * to compute nodes and containers/VMs on the compute nodes directly attached
-     * to the switch.
-     *
-     * @param macAddr the mac addr for the simple next objective
-     * @param vlanId the vlan for the simple next objective
-     * @param port port with which to create the Next Obj.
-     * @param createIfMissing true if a next object should be created if not found
-     * @return int if found or created, -1 if there are errors during the
-     *          creation of the next objective.
-     */
-    public int getMacVlanNextObjectiveId(MacAddress macAddr, VlanId vlanId, PortNumber port,
-                                      boolean createIfMissing) {
-
-        Integer nextId = macVlanNextObjStore
-                .get(new MacVlanNextObjectiveStoreKey(deviceId, macAddr, vlanId));
-
-        if (nextId != null) {
-            return nextId;
-        }
-
-        log.debug("getMacVlanNextObjectiveId in device {}: Next objective id "
-                + "not found for host : {}/{} .. {}", deviceId, macAddr, vlanId,
-                (createIfMissing) ? "creating" : "aborting");
-
-        if (!createIfMissing) {
-            return -1;
-        }
-
-        MacAddress deviceMac;
-        try {
-            deviceMac = deviceConfig.getDeviceMac(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " in getMacVlanNextObjectiveId");
-            return -1;
-        }
-
-        // since we are creating now, port cannot be null
-        if (port == null) {
-           log.debug("getMacVlanNextObjectiveId : port information cannot be null "
-                          + "for device {}, host {}/{}", deviceId, macAddr, vlanId);
-           return -1;
-        }
-
-        TrafficSelector.Builder meta = DefaultTrafficSelector.builder();
-
-        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-        treatment.deferred()
-                .setEthDst(macAddr)
-                .setEthSrc(deviceMac)
-                .setOutput(port);
-
-        ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
-        VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
-        Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
-        VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
-        // Adjust the meta according to VLAN configuration
-        if (taggedVlans.contains(vlanId)) {
-            treatment.setVlanId(vlanId);
-        } else if (vlanId.equals(VlanId.NONE)) {
-            if (untaggedVlan != null) {
-                meta.matchVlanId(untaggedVlan);
-            } else if (nativeVlan != null) {
-                meta.matchVlanId(nativeVlan);
-            } else {
-                log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan",
-                        macAddr, vlanId, connectPoint);
-                return -1;
-            }
-        } else {
-            log.warn("Tagged nexthop {}/{} is not allowed on {} without VLAN listed"
-                    + " in tagged vlan", macAddr, vlanId, connectPoint);
-            return -1;
-        }
-
-        /* create missing next objective */
-        nextId = createGroupFromMacVlan(macAddr, vlanId, treatment.build(), meta.build());
-        if (nextId == null) {
-            log.warn("getMacVlanNextObjectiveId: unable to create next obj"
-                    + "for dev:{} host:{}/{}", deviceId, macAddr, vlanId);
-            return -1;
-        }
-        return nextId;
-    }
-
-
-    /**
-     * Returns the next objective of type simple associated with the port on the
-     * device, given the treatment. Different treatments to the same port result
-     * in different next objectives. If no such objective exists, this method
-     * creates one (if requested) and returns the id. Optionally metadata can be passed in for
-     * the creation of the objective. Typically this is used for L2 and L3 forwarding
-     * to compute nodes and containers/VMs on the compute nodes directly attached
-     * to the switch.
-     *
-     * @param portNum the port number for the simple next objective
-     * @param treatment the actions to apply on the packets (should include outport)
-     * @param meta optional metadata passed into the creation of the next objective
-     * @param createIfMissing true if a next object should be created if not found
-     * @return int if found or created, -1 if there are errors during the
-     *          creation of the next objective.
-     */
-    public int getPortNextObjectiveId(PortNumber portNum, TrafficTreatment treatment,
-                                      TrafficSelector meta, boolean createIfMissing) {
-        Integer nextId = portNextObjStore
-                .get(new PortNextObjectiveStoreKey(deviceId, portNum, treatment, meta));
-        if (nextId != null) {
-            return nextId;
-        }
-        log.debug("getPortNextObjectiveId in device {}: Next objective id "
-                + "not found for port: {} .. {}", deviceId, portNum,
-                (createIfMissing) ? "creating" : "aborting");
-        if (!createIfMissing) {
-            return -1;
-        }
-        // create missing next objective
-        createGroupFromPort(portNum, treatment, meta);
-        nextId = portNextObjStore.get(new PortNextObjectiveStoreKey(deviceId, portNum,
-                                                                    treatment, meta));
-        if (nextId == null) {
-            log.warn("getPortNextObjectiveId: unable to create next obj"
-                    + "for dev:{} port:{}", deviceId, portNum);
-            return -1;
-        }
-        return nextId;
-    }
-
-    /**
-     * Checks if the next objective ID (group) for the neighbor set exists or not.
-     *
-     * @param ns neighbor set to check
-     * @return true if it exists, false otherwise
-     */
-    public boolean hasNextObjectiveId(DestinationSet ns) {
-        NextNeighbors nextHops = dsNextObjStore.
-                get(new DestinationSetNextObjectiveStoreKey(deviceId, ns));
-        if (nextHops == null) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private void populateNeighborMaps() {
-        Set<Link> outgoingLinks = linkService.getDeviceEgressLinks(deviceId);
-        for (Link link : outgoingLinks) {
-            if (link.type() != Link.Type.DIRECT) {
-                continue;
-            }
-            addNeighborAtPort(link.dst().deviceId(), link.src().port());
-        }
-    }
-
-    protected void addNeighborAtPort(DeviceId neighborId,
-                                     PortNumber portToNeighbor) {
-        // Update DeviceToPort database
-        log.debug("Device {} addNeighborAtPort: neighbor {} at port {}",
-                  deviceId, neighborId, portToNeighbor);
-        Set<PortNumber> ports = Collections
-                .newSetFromMap(new ConcurrentHashMap<PortNumber, Boolean>());
-        ports.add(portToNeighbor);
-        Set<PortNumber> portnums = devicePortMap.putIfAbsent(neighborId, ports);
-        if (portnums != null) {
-            portnums.add(portToNeighbor);
-        }
-
-        // Update portToDevice database
-        // should always update as neighbor could have changed on this port
-        DeviceId prev = portDeviceMap.put(portToNeighbor, neighborId);
-        if (prev != null) {
-            log.warn("Device/port: {}/{} previous neighbor: {}, current neighbor: {} ",
-                      deviceId, portToNeighbor, prev, neighborId);
-        }
-    }
-
-    /**
-     * Creates a NextObjective for a hash group in this device from a given
-     * DestinationSet. If the parameter simple is true, a simple next objective
-     * is created instead.
-     *
-     * @param ds the DestinationSet
-     * @param neighbors a map for each destination and its next-hops
-     * @param meta metadata passed into the creation of a Next Objective
-     * @param simple if true, a simple next objective will be created instead of
-     *            a hashed next objective
-     */
-    public void createGroupFromDestinationSet(DestinationSet ds,
-                                              Map<DeviceId, Set<DeviceId>> neighbors,
-                                              TrafficSelector meta,
-                                              boolean simple) {
-        int nextId = flowObjectiveService.allocateNextId();
-        NextObjective.Type type = (simple) ? NextObjective.Type.SIMPLE
-                                           : NextObjective.Type.HASHED;
-        if (neighbors == null || neighbors.isEmpty()) {
-            log.warn("createGroupsFromDestinationSet: needs at least one neighbor"
-                    + "to create group in dev:{} for ds: {} with next-hops {}",
-                    deviceId, ds, neighbors);
-            return;
-        }
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder()
-                .withId(nextId)
-                .withType(type)
-                .fromApp(appId);
-        if (meta != null) {
-            nextObjBuilder.withMeta(meta);
-        }
-
-        // create treatment buckets for each neighbor for each dst Device
-        // except in the special case where we only want to pick a single
-        // neighbor/port for a simple nextObj
-        boolean foundSingleNeighbor = false;
-        boolean treatmentAdded = false;
-        Map<DeviceId, Set<DeviceId>> dstNextHops = new ConcurrentHashMap<>();
-        for (DeviceId dst : ds.getDestinationSwitches()) {
-            Set<DeviceId> nextHops = neighbors.get(dst);
-            if (nextHops == null || nextHops.isEmpty()) {
-                continue;
-            }
-
-            if (foundSingleNeighbor) {
-                break;
-            }
-
-            for (DeviceId neighborId : nextHops) {
-                if (devicePortMap.get(neighborId) == null) {
-                    log.warn("Neighbor {} is not in the port map yet for dev:{}",
-                             neighborId, deviceId);
-                    return;
-                } else if (devicePortMap.get(neighborId).isEmpty()) {
-                    log.warn("There are no ports for "
-                            + "the Device {} in the port map yet", neighborId);
-                    return;
-                }
-
-                MacAddress neighborMac;
-                try {
-                    neighborMac = deviceConfig.getDeviceMac(neighborId);
-                } catch (DeviceConfigNotFoundException e) {
-                    log.warn(e.getMessage() + " Aborting createGroupsFromDestinationset.");
-                    return;
-                }
-                // For each port to the neighbor, we create a new treatment
-                Set<PortNumber> neighborPorts = devicePortMap.get(neighborId);
-                // In this case we need a SIMPLE nextObj. We randomly pick a port
-                if (simple) {
-                    int size = devicePortMap.get(neighborId).size();
-                    int index = RandomUtils.nextInt(0, size);
-                    neighborPorts = Collections.singleton(
-                                        Iterables.get(devicePortMap.get(neighborId),
-                                                      index));
-                    foundSingleNeighbor = true;
-                }
-
-                for (PortNumber sp : neighborPorts) {
-                    TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
-                            .builder();
-                    tBuilder.setEthDst(neighborMac).setEthSrc(nodeMacAddr);
-                    int edgeLabel = ds.getEdgeLabel(dst);
-                    if (edgeLabel != DestinationSet.NO_EDGE_LABEL) {
-                        if (simple) {
-                            // swap label case
-                            tBuilder.setMpls(MplsLabel.mplsLabel(edgeLabel));
-                        } else {
-                            // ecmp with label push case
-                            tBuilder.pushMpls().copyTtlOut()
-                                    .setMpls(MplsLabel.mplsLabel(edgeLabel));
-                        }
-                    }
-
-                    // Set VLAN ID for PW transport. Otherwise pop vlan
-                    if (!popVlanInHashGroup(ds)) {
-                        tBuilder.setVlanId(srManager.getPwTransportVlan());
-                    } else {
-                        tBuilder.popVlan();
-                    }
-
-                    tBuilder.setOutput(sp);
-                    nextObjBuilder.addTreatment(tBuilder.build());
-                    treatmentAdded = true;
-                    //update store
-                    Set<DeviceId> existingNeighbors = dstNextHops.get(dst);
-                    if (existingNeighbors == null) {
-                        existingNeighbors = new HashSet<>();
-                    }
-                    existingNeighbors.add(neighborId);
-                    dstNextHops.put(dst, existingNeighbors);
-                    log.debug("creating treatment for port/label {}/{} in next:{}",
-                              sp, edgeLabel, nextId);
-                }
-
-                if (foundSingleNeighbor) {
-                    break;
-                }
-            }
-        }
-
-        if (!treatmentAdded) {
-            log.warn("Could not createGroup from DestinationSet {} without any"
-                    + "next hops {}", ds, neighbors);
-            return;
-        }
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) ->
-                log.debug("createGroupsFromDestinationSet installed "
-                        + "NextObj {} on {}", nextId, deviceId),
-                (objective, error) -> {
-                    log.warn("createGroupsFromDestinationSet failed to install NextObj {} on {}: {}",
-                            nextId, deviceId, error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-        NextObjective nextObj = nextObjBuilder.add(context);
-        log.debug(".. createGroupsFromDestinationSet: Submitted "
-                + "next objective {} in device {}", nextId, deviceId);
-        flowObjectiveService.next(deviceId, nextObj);
-        //update store
-        dsNextObjStore.put(new DestinationSetNextObjectiveStoreKey(deviceId, ds),
-                           new NextNeighbors(dstNextHops, nextId));
-    }
-
-    /**
-     * Creates broadcast groups for all ports in the same subnet for
-     * all configured subnets.
-     */
-    public void createGroupsFromVlanConfig() {
-        srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
-            createBcastGroupFromVlan(vlanId, ports);
-        });
-    }
-
-    /**
-     * Creates a single broadcast group from a given vlan id and list of ports.
-     *
-     * @param vlanId vlan id
-     * @param ports list of ports in the subnet
-     */
-    public void createBcastGroupFromVlan(VlanId vlanId, Collection<PortNumber> ports) {
-        VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
-        if (vlanNextObjStore.containsKey(key)) {
-            log.debug("Broadcast group for device {} and subnet {} exists",
-                      deviceId, vlanId);
-            return;
-        }
-
-        TrafficSelector metadata =
-                DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
-        int nextId = flowObjectiveService.allocateNextId();
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.BROADCAST).fromApp(appId)
-                .withMeta(metadata);
-
-        ports.forEach(port -> {
-            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-            if (toPopVlan(port, vlanId)) {
-                tBuilder.popVlan();
-            }
-            tBuilder.setOutput(port);
-            nextObjBuilder.addTreatment(tBuilder.build());
-        });
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-            (objective) ->
-                log.debug("createBroadcastGroupFromVlan installed "
-                        + "NextObj {} on {}", nextId, deviceId),
-            (objective, error) -> {
-                log.warn("createBroadcastGroupFromVlan failed to install NextObj {} on {}: {}",
-                        nextId, deviceId, error);
-                srManager.invalidateNextObj(objective.id());
-            });
-        NextObjective nextObj = nextObjBuilder.add(context);
-        flowObjectiveService.next(deviceId, nextObj);
-        log.debug("createBcastGroupFromVlan: Submitted next objective {} "
-                + "for vlan: {} in device {}", nextId, vlanId, deviceId);
-
-        vlanNextObjStore.put(key, nextId);
-    }
-
-    /**
-     * Removes a single broadcast group from a given vlan id.
-     * The group should be empty.
-     * @param deviceId device Id to remove the group
-     * @param portNum port number related to the group
-     * @param vlanId vlan id of the broadcast group to remove
-     * @param popVlan true if the TrafficTreatment involves pop vlan tag action
-     */
-    public void removeBcastGroupFromVlan(DeviceId deviceId, PortNumber portNum,
-                                         VlanId vlanId, boolean popVlan) {
-        VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
-        if (!vlanNextObjStore.containsKey(key)) {
-            log.debug("Broadcast group for device {} and subnet {} does not exist",
-                      deviceId, vlanId);
-            return;
-        }
-
-        TrafficSelector metadata =
-                DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
-        int nextId = vlanNextObjStore.get(key);
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.BROADCAST).fromApp(appId)
-                .withMeta(metadata);
-
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        if (popVlan) {
-            tBuilder.popVlan();
-        }
-        tBuilder.setOutput(portNum);
-        nextObjBuilder.addTreatment(tBuilder.build());
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) ->
-                        log.debug("removeBroadcastGroupFromVlan removed "
-                                          + "NextObj {} on {}", nextId, deviceId),
-                (objective, error) -> {
-                    log.warn("removeBroadcastGroupFromVlan failed to remove NextObj {} on {}: {}",
-                            nextId, deviceId, error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-        NextObjective nextObj = nextObjBuilder.remove(context);
-        flowObjectiveService.next(deviceId, nextObj);
-        log.debug("removeBcastGroupFromVlan: Submited next objective {} in device {}",
-                  nextId, deviceId);
-
-        vlanNextObjStore.remove(key, nextId);
-    }
-
-    /**
-     * Determine if we should pop given vlan before sending packets to the given port.
-     *
-     * @param portNumber port number
-     * @param vlanId vlan id
-     * @return true if the vlan id is not contained in any vlanTagged config
-     */
-    private boolean toPopVlan(PortNumber portNumber, VlanId vlanId) {
-        return srManager.interfaceService
-                .getInterfacesByPort(new ConnectPoint(deviceId, portNumber))
-                .stream().noneMatch(intf -> intf.vlanTagged().contains(vlanId));
-    }
-
-    /**
-     * Create simple next objective for an indirect host mac/vlan. The treatments can include
-     * all outgoing actions that need to happen on the packet.
-     *
-     * @param macAddr the mac address of the host
-     * @param vlanId the vlan of the host
-     * @param treatment the actions to apply on the packets (should include outport)
-     * @param meta optional data to pass to the driver
-     * @return next objective ID
-     */
-    public int createGroupFromMacVlan(MacAddress macAddr, VlanId vlanId, TrafficTreatment treatment,
-                                    TrafficSelector meta) {
-        int nextId = flowObjectiveService.allocateNextId();
-        MacVlanNextObjectiveStoreKey key = new MacVlanNextObjectiveStoreKey(deviceId, macAddr, vlanId);
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.SIMPLE)
-                .addTreatment(treatment)
-                .fromApp(appId)
-                .withMeta(meta);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-            (objective) ->
-                log.debug("createGroupFromMacVlan installed "
-                        + "NextObj {} on {}", nextId, deviceId),
-            (objective, error) -> {
-                log.warn("createGroupFromMacVlan failed to install NextObj {} on {}: {}", nextId, deviceId, error);
-                srManager.invalidateNextObj(objective.id());
-            });
-        NextObjective nextObj = nextObjBuilder.add(context);
-        flowObjectiveService.next(deviceId, nextObj);
-        log.debug("createGroupFromMacVlan: Submited next objective {} in device {} "
-                + "for host {}/{}", nextId, deviceId, macAddr, vlanId);
-
-        macVlanNextObjStore.put(key, nextId);
-        return nextId;
-    }
-
-    /**
-     * Create simple next objective for a single port. The treatments can include
-     * all outgoing actions that need to happen on the packet.
-     *
-     * @param portNum  the outgoing port on the device
-     * @param treatment the actions to apply on the packets (should include outport)
-     * @param meta optional data to pass to the driver
-     */
-    public void createGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
-                                    TrafficSelector meta) {
-        int nextId = flowObjectiveService.allocateNextId();
-        PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
-                                                deviceId, portNum, treatment, meta);
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.SIMPLE)
-                .addTreatment(treatment)
-                .fromApp(appId)
-                .withMeta(meta);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-            (objective) ->
-                log.debug("createGroupFromPort installed "
-                        + "NextObj {} on {}", nextId, deviceId),
-            (objective, error) -> {
-                log.warn("createGroupFromPort failed to install NextObj {} on {}: {}", nextId, deviceId, error);
-                srManager.invalidateNextObj(objective.id());
-            });
-        NextObjective nextObj = nextObjBuilder.add(context);
-        flowObjectiveService.next(deviceId, nextObj);
-        log.debug("createGroupFromPort: Submited next objective {} in device {} "
-                + "for port {}", nextId, deviceId, portNum);
-
-        portNextObjStore.put(key, nextId);
-    }
-
-    /**
-     * Creates simple next objective for a single port.
-     *
-     * @param deviceId device id that has the port to deal with
-     * @param portNum the outgoing port on the device
-     * @param vlanId vlan id associated with the port
-     * @param popVlan true if POP_VLAN action is applied on the packets, false otherwise
-     */
-    public void createPortNextObjective(DeviceId deviceId, PortNumber portNum, VlanId vlanId, boolean popVlan) {
-        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-        mbuilder.matchVlanId(vlanId);
-
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.immediate().setOutput(portNum);
-        if (popVlan) {
-            tbuilder.immediate().popVlan();
-        }
-
-        createGroupFromPort(portNum, tbuilder.build(), mbuilder.build());
-    }
-
-    /**
-     * Removes simple next objective for a single port.
-     *
-     * @param deviceId device id that has the port to deal with
-     * @param portNum the outgoing port on the device
-     * @param vlanId vlan id associated with the port
-     * @param popVlan true if POP_VLAN action is applied on the packets, false otherwise
-     */
-    public void removePortNextObjective(DeviceId deviceId, PortNumber portNum, VlanId vlanId, boolean popVlan) {
-        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-        mbuilder.matchVlanId(vlanId);
-
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.immediate().setOutput(portNum);
-        if (popVlan) {
-            tbuilder.immediate().popVlan();
-        }
-
-        int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNum,
-                                                             tbuilder.build(), mbuilder.build(), false);
-
-        PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
-                deviceId, portNum, tbuilder.build(), mbuilder.build());
-        if (portNextObjId != -1 && portNextObjStore.containsKey(key)) {
-            NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                    .builder().withId(portNextObjId)
-                    .withType(NextObjective.Type.SIMPLE).fromApp(appId);
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("removePortNextObjective removes NextObj {} on {}",
-                                             portNextObjId, deviceId),
-                    (objective, error) -> {
-                        log.warn("removePortNextObjective failed to remove NextObj {} on {}: {}",
-                                portNextObjId, deviceId, error);
-                        srManager.invalidateNextObj(objective.id());
-                    });
-            NextObjective nextObjective = nextObjBuilder.remove(context);
-            log.info("**removePortNextObjective: Submitted "
-                             + "next objective {} in device {}",
-                     portNextObjId, deviceId);
-            flowObjectiveService.next(deviceId, nextObjective);
-
-            portNextObjStore.remove(key);
-        }
-    }
-
-    /**
-     * Removes groups for the next objective ID given.
-     *
-     * @param objectiveId next objective ID to remove
-     * @return true if succeeds, false otherwise
-     */
-    public boolean removeGroup(int objectiveId) {
-        for (Map.Entry<DestinationSetNextObjectiveStoreKey, NextNeighbors> e :
-                dsNextObjStore.entrySet()) {
-            if (e.getValue().nextId() != objectiveId) {
-                continue;
-            }
-            // Right now it is just used in TunnelHandler
-            // remember in future that PW transit groups could
-            // be Indirect groups
-            NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                    .builder().withId(objectiveId)
-                    .withType(NextObjective.Type.HASHED).fromApp(appId);
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("RemoveGroup removes NextObj {} on {}",
-                            objectiveId, deviceId),
-                    (objective, error) -> {
-                        log.warn("RemoveGroup failed to remove NextObj {} on {}: {}", objectiveId, deviceId, error);
-                        srManager.invalidateNextObj(objective.id());
-                    });
-            NextObjective nextObjective = nextObjBuilder.remove(context);
-            log.info("**removeGroup: Submited "
-                    + "next objective {} in device {}",
-                    objectiveId, deviceId);
-            flowObjectiveService.next(deviceId, nextObjective);
-
-            dsNextObjStore.remove(e.getKey());
-            return true;
-        }
-
-        return false;
-    }
-    /**
-     * Remove simple next objective for a single port. The treatments can include
-     * all outgoing actions that need to happen on the packet.
-     *
-     * @param portNum  the outgoing port on the device
-     * @param treatment the actions applied on the packets (should include outport)
-     * @param meta optional data to pass to the driver
-     */
-    public void removeGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
-                                    TrafficSelector meta) {
-        PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
-                deviceId, portNum, treatment, meta);
-        Integer nextId = portNextObjStore.get(key);
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.SIMPLE)
-                .addTreatment(treatment)
-                .fromApp(appId)
-                .withMeta(meta);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) ->
-                        log.info("removeGroupFromPort installed "
-                                          + "NextObj {} on {}", nextId, deviceId),
-                (objective, error) -> {
-                    log.warn("removeGroupFromPort failed to install NextObj {} on {}: {}", nextId, deviceId, error);
-                    srManager.invalidateNextObj(objective.id());
-                }
-        );
-        NextObjective nextObj = nextObjBuilder.remove(context);
-        flowObjectiveService.next(deviceId, nextObj);
-        log.info("removeGroupFromPort: Submitted next objective {} in device {} "
-                          + "for port {}", nextId, deviceId, portNum);
-
-        portNextObjStore.remove(key);
-    }
-
-    /**
-     * Removes all groups from all next objective stores.
-     */
-    /*public void removeAllGroups() {
-        for (Map.Entry<NeighborSetNextObjectiveStoreKey, NextNeighbors> entry:
-                nsNextObjStore.entrySet()) {
-            removeGroup(entry.getValue().nextId());
-        }
-        for (Map.Entry<PortNextObjectiveStoreKey, Integer> entry:
-                portNextObjStore.entrySet()) {
-            removeGroup(entry.getValue());
-        }
-        for (Map.Entry<VlanNextObjectiveStoreKey, Integer> entry:
-                vlanNextObjStore.entrySet()) {
-            removeGroup(entry.getValue());
-        }
-    }*/ //XXX revisit
-
-    /**
-     * Triggers a one time bucket verification operation on all hash groups
-     * on this device.
-     */
-    public void triggerBucketCorrector() {
-        BucketCorrector bc = new BucketCorrector();
-        bc.run();
-    }
-
-    /**
-     * Modifies L2IG bucket when the interface configuration is updated, especially
-     * when the interface has same VLAN ID but the VLAN type is changed (e.g., from
-     * vlan-tagged [10] to vlan-untagged 10), which requires changes on
-     * TrafficTreatment in turn.
-     *
-     * @param portNumber the port on this device that needs to be updated
-     * @param vlanId the vlan id corresponding to this port
-     * @param pushVlan indicates if packets should be sent out untagged or not out
-     *                 from the port. If true, updated TrafficTreatment involves
-     *                 pop vlan tag action. If false, updated TrafficTreatment
-     *                 does not involve pop vlan tag action.
-     */
-    public void updateL2InterfaceGroupBucket(PortNumber portNumber, VlanId vlanId, boolean pushVlan) {
-        TrafficTreatment.Builder oldTBuilder = DefaultTrafficTreatment.builder();
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        tBuilder.setOutput(portNumber);
-        oldTBuilder.setOutput(portNumber);
-        if (pushVlan) {
-            tBuilder.popVlan();
-        } else {
-            oldTBuilder.popVlan();
-        }
-
-        TrafficSelector metadata =
-                DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
-        // Update portNextObjStore with new L2IG
-        int nextId = getPortNextObjectiveId(portNumber, oldTBuilder.build(), metadata, false);
-        portNextObjStore.remove(new PortNextObjectiveStoreKey(deviceId, portNumber, oldTBuilder.build(), metadata));
-        portNextObjStore.put(new PortNextObjectiveStoreKey(deviceId, portNumber, tBuilder.build(), metadata), nextId);
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.SIMPLE).fromApp(appId)
-                .addTreatment(tBuilder.build())
-                .withMeta(metadata);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("port {} successfully updated NextObj {} on {}",
-                                         portNumber, nextId, deviceId),
-                (objective, error) -> {
-                    log.warn("port {} failed to updated NextObj {} on {}: {}", portNumber, nextId, deviceId, error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-
-        flowObjectiveService.next(deviceId, nextObjBuilder.modify(context));
-    }
-
-    /**
-     * Updates the next objective for the given nextId .
-     *
-     * @param hostMac mac of host for which Next obj is to be updated.
-     * @param hostVlanId vlan of host for which Next obj is to be updated.
-     * @param port port with which to update the Next Obj.
-     * @param nextId of Next Obj which needs to be updated.
-     */
-    public void updateL3UcastGroupBucket(MacAddress hostMac, VlanId hostVlanId, PortNumber port, int nextId) {
-
-       MacAddress deviceMac;
-        try {
-            deviceMac = deviceConfig.getDeviceMac(deviceId);
-        } catch (DeviceConfigNotFoundException e) {
-            log.warn(e.getMessage() + " in updateL3UcastGroupBucket");
-            return;
-        }
-
-        TrafficSelector metadata =
-                 DefaultTrafficSelector.builder().matchVlanId(hostVlanId).build();
-
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-        tbuilder.deferred()
-                .setEthDst(hostMac)
-                .setEthSrc(deviceMac)
-                .setVlanId(hostVlanId)
-                .setOutput(port);
-
-        log.debug(" update L3Ucast : deviceMac {}, port {}, host {}/{}, nextid {}, Treatment {} Meta {}",
-                                     deviceMac, port, hostMac, hostVlanId, nextId, tbuilder.build(), metadata);
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.SIMPLE).fromApp(appId)
-                .addTreatment(tbuilder.build())
-                .withMeta(metadata);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug(" NextId {} successfully updated host {} vlan {} with port {}",
-                                         nextId, hostMac, hostVlanId, port),
-                (objective, error) -> {
-                    log.warn(" NextId {} failed to update host {} vlan {} with port {}, error : {}",
-                                         nextId, hostMac, hostVlanId, port, error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-
-        NextObjective nextObj = nextObjBuilder.modify(context);
-        flowObjectiveService.next(deviceId, nextObj);
-
-    }
-
-    /**
-     * Adds a single port to the L2FG or removes it from the L2FG.
-     *
-     * @param vlanId the vlan id corresponding to this port
-     * @param portNum the port on this device to be updated
-     * @param nextId the next objective ID for the given vlan id
-     * @param install if true, adds the port to L2FG. If false, removes it from L2FG.
-     */
-    public void updateGroupFromVlanConfiguration(VlanId vlanId, PortNumber portNum, int nextId, boolean install) {
-        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        if (toPopVlan(portNum, vlanId)) {
-            tBuilder.popVlan();
-        }
-        tBuilder.setOutput(portNum);
-
-        TrafficSelector metadata =
-                DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.BROADCAST).fromApp(appId)
-                .addTreatment(tBuilder.build())
-                .withMeta(metadata);
-
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("port {} successfully removedFrom NextObj {} on {}",
-                                         portNum, nextId, deviceId),
-                (objective, error) -> {
-                    log.warn("port {} failed to removedFrom NextObj {} on {}: {}", portNum, nextId, deviceId, error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-
-        if (install) {
-            flowObjectiveService.next(deviceId, nextObjBuilder.addToExisting(context));
-        } else {
-            flowObjectiveService.next(deviceId, nextObjBuilder.removeFromExisting(context));
-        }
-    }
-
-    /**
-     * Performs bucket verification operation for all hash groups in this device.
-     * Checks RouteHandler to ensure that routing is stable before attempting
-     * verification. Verification involves creating a nextObjective with
-     * operation VERIFY for existing next objectives in the store, and passing
-     * it to the driver. It is the driver that actually performs the verification
-     * by adding or removing buckets to match the verification next objective
-     * created here.
-     */
-    protected final class BucketCorrector implements Runnable {
-        Integer nextId;
-
-        BucketCorrector() {
-            this.nextId = null;
-        }
-
-        BucketCorrector(Integer nextId) {
-            this.nextId = nextId;
-        }
-
-        @Override
-        public void run() {
-            if (!srManager.mastershipService.isLocalMaster(deviceId)) {
-                return;
-            }
-            DefaultRoutingHandler rh = srManager.getRoutingHandler();
-            if (rh == null) {
-                return;
-            }
-            if (!rh.isRoutingStable()) {
-                return;
-            }
-            rh.acquireRoutingLock();
-            try {
-                log.trace("running bucket corrector for dev: {}", deviceId);
-                Set<DestinationSetNextObjectiveStoreKey> dsKeySet = dsNextObjStore.entrySet()
-                        .stream()
-                        .filter(entry -> entry.getKey().deviceId().equals(deviceId))
-                        // Filter out PW transit groups or include them if MPLS ECMP is supported
-                        .filter(entry -> !entry.getKey().destinationSet().notBos() ||
-                                (entry.getKey().destinationSet().notBos() && srManager.getMplsEcmp()))
-                        // Filter out simple SWAP groups or include them if MPLS ECMP is supported
-                        .filter(entry -> !entry.getKey().destinationSet().swap() ||
-                                (entry.getKey().destinationSet().swap() && srManager.getMplsEcmp()))
-                        .map(entry -> entry.getKey())
-                        .collect(Collectors.toSet());
-                for (DestinationSetNextObjectiveStoreKey dsKey : dsKeySet) {
-                    NextNeighbors next = dsNextObjStore.get(dsKey);
-                    if (next == null) {
-                        continue;
-                    }
-                    int nid = next.nextId();
-                    if (nextId != null && nextId != nid) {
-                        continue;
-                    }
-                    log.trace("bkt-corr: dsNextObjStore for device {}: {}",
-                              deviceId, dsKey, next);
-                    TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
-                    metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
-                    NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
-                            .withId(nid)
-                            .withType(NextObjective.Type.HASHED)
-                            .withMeta(metabuilder.build())
-                            .fromApp(appId);
-
-                    next.dstNextHops().forEach((dstDev, nextHops) -> {
-                        int edgeLabel = dsKey.destinationSet().getEdgeLabel(dstDev);
-                        nextHops.forEach(neighbor -> {
-                            MacAddress neighborMac;
-                            try {
-                                neighborMac = deviceConfig.getDeviceMac(neighbor);
-                            } catch (DeviceConfigNotFoundException e) {
-                                log.warn(e.getMessage() + " Aborting neighbor"
-                                        + neighbor);
-                                return;
-                            }
-                            devicePortMap.get(neighbor).forEach(port -> {
-                                log.trace("verify in device {} nextId {}: bucket with"
-                                        + " port/label {}/{} to dst {} via {}",
-                                        deviceId, nid, port, edgeLabel,
-                                        dstDev, neighbor);
-                                nextObjBuilder
-                                    .addTreatment(treatmentBuilder(port,
-                                                                   neighborMac,
-                                                                   dsKey.destinationSet().swap(),
-                                                                   edgeLabel));
-                            });
-                        });
-                    });
-
-                    NextObjective nextObjective = nextObjBuilder.verify();
-                    flowObjectiveService.next(deviceId, nextObjective);
-                }
-            } finally {
-                rh.releaseRoutingLock();
-            }
-
-        }
-
-        TrafficTreatment treatmentBuilder(PortNumber outport, MacAddress dstMac,
-                                          boolean swap, int edgeLabel) {
-            TrafficTreatment.Builder tBuilder =
-                    DefaultTrafficTreatment.builder();
-            tBuilder.setOutput(outport)
-                .setEthDst(dstMac)
-                .setEthSrc(nodeMacAddr);
-            if (edgeLabel != DestinationSet.NO_EDGE_LABEL) {
-                if (swap) {
-                    // swap label case
-                    tBuilder.setMpls(MplsLabel.mplsLabel(edgeLabel));
-                } else {
-                    // ecmp with label push case
-                    tBuilder.pushMpls()
-                        .copyTtlOut()
-                        .setMpls(MplsLabel.mplsLabel(edgeLabel));
-                }
-            }
-            return tBuilder.build();
-        }
-    }
-
-    /**
-     * Determines whether the hash group bucket should include a popVlan action.
-     * We don't popVlan for PW.
-     *
-     * @param ds destination set
-     * @return true if VLAN needs to be popped
-     */
-    private boolean popVlanInHashGroup(DestinationSet ds) {
-        return (ds.getTypeOfDstSet() != DestinationSet.DestinationSetType.SWAP_NOT_BOS) &&
-                (ds.getTypeOfDstSet() != DestinationSet.DestinationSetType.POP_NOT_BOS);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java
deleted file mode 100644
index 3ecdd61..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * 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.grouphandler;
-
-import org.onosproject.net.DeviceId;
-import org.slf4j.Logger;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Representation of a set of destination switch dpids along with their
- * edge-node labels. Meant to be used as a lookup-key in a hash-map to retrieve
- * an ECMP-group that hashes packets towards a specific destination switch, or
- * paired-destination switches. May also be used to represent cases where the
- * forwarding does not use ECMP groups (ie SIMPLE next objectives)
- */
-public final class DestinationSet {
-    public static final int NO_EDGE_LABEL = -1;
-    private static final int NOT_ASSIGNED = 0;
-    private final DeviceId dstSw1;
-    private final int edgeLabel1;
-    private final DeviceId dstSw2;
-    private final int edgeLabel2;
-    private final DestinationSetType typeOfDstSet;
-
-    private static final Logger log = getLogger(DestinationSet.class);
-
-    /**
-     * Constructor for a single destination with no Edge label.
-     *
-     * @param dsType type of next objective
-     * @param dstSw the destination switch
-     */
-    private DestinationSet(DestinationSetType dsType, DeviceId dstSw) {
-        this.edgeLabel1 = NO_EDGE_LABEL;
-        this.dstSw1 = dstSw;
-        this.edgeLabel2 = NOT_ASSIGNED;
-        this.dstSw2 = null;
-        this.typeOfDstSet = dsType;
-    }
-
-    /**
-     * Constructor for a single destination with Edge label.
-     *
-     * @param dsType type of next objective
-     * @param edgeLabel label to be pushed as part of group operation
-     * @param dstSw the destination switch
-     */
-    private DestinationSet(DestinationSetType dsType,
-                          int edgeLabel, DeviceId dstSw) {
-        this.edgeLabel1 = edgeLabel;
-        this.dstSw1 = dstSw;
-        this.edgeLabel2 = NOT_ASSIGNED;
-        this.dstSw2 = null;
-        this.typeOfDstSet = dsType;
-    }
-
-    /**
-     * Constructor for paired destination switches and their associated edge
-     * labels.
-     *
-     * @param dsType type of next objective
-     * @param edgeLabel1 label to be pushed as part of group operation for
-     *            dstSw1
-     * @param dstSw1 one of the paired destination switches
-     * @param edgeLabel2 label to be pushed as part of group operation for
-     *            dstSw2
-     * @param dstSw2 the other paired destination switch
-     */
-    private DestinationSet(DestinationSetType dsType,
-                          int edgeLabel1, DeviceId dstSw1,
-                          int edgeLabel2, DeviceId dstSw2) {
-        if (dstSw1.toString().compareTo(dstSw2.toString()) <= 0) {
-            this.edgeLabel1 = edgeLabel1;
-            this.dstSw1 = dstSw1;
-            this.edgeLabel2 = edgeLabel2;
-            this.dstSw2 = dstSw2;
-        } else {
-            this.edgeLabel1 = edgeLabel2;
-            this.dstSw1 = dstSw2;
-            this.edgeLabel2 = edgeLabel1;
-            this.dstSw2 = dstSw1;
-        }
-        this.typeOfDstSet = dsType;
-    }
-    /**
-     * Default constructor for kryo serialization.
-     */
-    private DestinationSet() {
-        this.edgeLabel1 = NOT_ASSIGNED;
-        this.edgeLabel2 = NOT_ASSIGNED;
-        this.dstSw1 = DeviceId.NONE;
-        this.dstSw2 = DeviceId.NONE;
-        this.typeOfDstSet = null;
-    }
-
-    /**
-     * Gets the label associated with given destination switch.
-     *
-     * @param dstSw the destination switch
-     * @return integer the label associated with the destination switch
-     */
-    public int getEdgeLabel(DeviceId dstSw) {
-        if (dstSw.equals(dstSw1)) {
-            return edgeLabel1;
-        } else if (dstSw.equals(dstSw2)) {
-            return edgeLabel2;
-        }
-        return NOT_ASSIGNED;
-    }
-
-    /**
-     * Gets all the destination switches in this destination set.
-     *
-     * @return a set of destination switch ids
-     */
-    public Set<DeviceId> getDestinationSwitches() {
-        Set<DeviceId> dests = new HashSet<>();
-        dests.add(dstSw1);
-        if (dstSw2 != null) {
-            dests.add(dstSw2);
-        }
-        return dests;
-    }
-
-    /**
-     * Returns the type of this ds.
-     *
-     * @return the type of the destination set
-     */
-    public DestinationSetType getTypeOfDstSet() {
-        return typeOfDstSet;
-    }
-
-    /**
-     * Returns true if the next objective represented by this destination set
-     * is of type SWAP_NOT_BOS or POP_NOT_BOS.
-     *
-     * @return the value of notBos
-     */
-    public boolean notBos() {
-        if ((typeOfDstSet == DestinationSetType.SWAP_NOT_BOS) || (typeOfDstSet == DestinationSetType.POP_NOT_BOS)) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if the next objective represented by this destination set
-     * is of type SWAP_NOT_BOS or SWAP_BOS.
-     *
-     * @return the value of swap
-     */
-    public boolean swap() {
-        if ((typeOfDstSet == DestinationSetType.SWAP_BOS) || (typeOfDstSet == DestinationSetType.SWAP_NOT_BOS)) {
-            return true;
-        }
-        return false;
-    }
-
-    // The list of destination ids and label are used for comparison.
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof DestinationSet)) {
-            return false;
-        }
-        DestinationSet that = (DestinationSet) o;
-        if (this.typeOfDstSet != that.typeOfDstSet) {
-            return false;
-        }
-        boolean equal = (this.edgeLabel1 == that.edgeLabel1 &&
-                            this.dstSw1.equals(that.dstSw1));
-        if (this.dstSw2 != null && that.dstSw2 == null ||
-                this.dstSw2 == null && that.dstSw2 != null) {
-            return false;
-        }
-        if (this.dstSw2 != null && that.dstSw2 != null) {
-            equal = equal && (this.edgeLabel2 == that.edgeLabel2 &&
-                                this.dstSw2.equals(that.dstSw2));
-        }
-        return equal;
-    }
-
-    // The list of destination ids and label are used for comparison.
-    @Override
-    public int hashCode() {
-        if (dstSw2 == null) {
-            return Objects.hash(typeOfDstSet, edgeLabel1, dstSw1);
-        }
-        return Objects.hash(typeOfDstSet, edgeLabel1, dstSw1, edgeLabel2,
-                            dstSw2);
-    }
-
-    @Override
-    public String toString() {
-        ToStringHelper h = toStringHelper(this)
-                                .add("Type", typeOfDstSet.getType())
-                                .add("DstSw1", dstSw1)
-                                .add("Label1", edgeLabel1);
-        if (dstSw2 != null) {
-            h.add("DstSw2", dstSw2)
-             .add("Label2", edgeLabel2);
-        }
-        return h.toString();
-    }
-
-    public enum DestinationSetType {
-        /**
-         * Used to represent DestinationSetType where the next hop
-         * is the same as the final destination.
-         */
-        PUSH_NONE("pushnon"),
-        /**
-         * Used to represent DestinationSetType where we need to
-         * push a single mpls label, that of the destination.
-         */
-        PUSH_BOS("pushbos"),
-        /**
-         * Used to represent DestinationSetType where we need to pop
-         * an mpls label which has the bos bit set.
-         */
-        POP_BOS("pop-bos"),
-        /**
-         * Used to represent DestinationSetType where we swap the outer
-         * mpls label with a new one, and where the outer label has the
-         * bos bit set.
-         */
-        SWAP_BOS("swapbos"),
-        /**
-         * Used to represent DestinationSetType where we need to pop
-         * an mpls label which does not have the bos bit set.
-         */
-        POP_NOT_BOS("popnbos"),
-        /**
-         * Used to represent DestinationSetType where we swap the outer
-         * mpls label with a new one, and where the outer label does not
-         * have the bos bit set.
-         */
-        SWAP_NOT_BOS("swap-nb");
-
-        private final String typeOfDstDest;
-        DestinationSetType(String s) {
-            typeOfDstDest = s;
-        }
-
-        public String getType() {
-            return typeOfDstDest;
-        }
-    }
-
-    /*
-     * Static methods for creating DestinationSet objects in
-     * order to remove ambiquity with multiple constructors.
-     */
-
-    /**
-     * Returns a DestinationSet with type PUSH_NONE.
-     *
-     * @param destSw The deviceId for this next objective.
-     * @return The DestinationSet of this type.
-     */
-    public static DestinationSet createTypePushNone(DeviceId destSw) {
-        return new DestinationSet(DestinationSetType.PUSH_NONE, destSw);
-    }
-
-    /**
-     * Returns a DestinationSet with type PUSH_BOS.
-     *
-     * @param edgeLabel1 The mpls label to push.
-     * @param destSw1 The device on which the label is assigned.
-     * @return The DestinationSet of this type.
-     */
-    public static DestinationSet createTypePushBos(int edgeLabel1, DeviceId destSw1) {
-        return new DestinationSet(DestinationSetType.PUSH_BOS, edgeLabel1, destSw1);
-    }
-
-    /**
-     * Returns a DestinationSet with type PUSH_BOS used for paired leafs.
-     *
-     * @param edgeLabel1 The label of first paired leaf.
-     * @param destSw1 The device id of first paired leaf.
-     * @param edgeLabel2 The label of the second leaf.
-     * @param destSw2 The device id of the second leaf.
-     * @return The DestinationSet of this type.
-     */
-    public static DestinationSet createTypePushBos(int edgeLabel1, DeviceId destSw1, int edgeLabel2, DeviceId destSw2) {
-        return new DestinationSet(DestinationSetType.PUSH_BOS, edgeLabel1, destSw1, edgeLabel2, destSw2);
-    }
-
-    /**
-     * Returns a DestinationSet with type POP_BOS.
-     *
-     * @param deviceId The deviceId for this next objective.
-     * @return The DestinationSet of this type.
-     */
-    public static DestinationSet createTypePopBos(DeviceId deviceId) {
-        return new DestinationSet(DestinationSetType.POP_BOS, deviceId);
-    }
-
-    /**
-     * Returns a DestinationSet with type SWAP_BOS.
-     *
-     * @param edgeLabel The edge label to swap with.
-     * @param deviceId The deviceId for this next objective.
-     * @return The DestinationSet of this type.
-     */
-    public static DestinationSet createTypeSwapBos(int edgeLabel, DeviceId deviceId) {
-        return new DestinationSet(DestinationSetType.SWAP_BOS, edgeLabel, deviceId);
-    }
-
-    /**
-     * Returns a DestinationSet with type POP_NOT_BOS.
-     *
-     * @param deviceId The device-id this next objective should be installed.
-     * @return The DestinationSet of this type.
-     */
-    public static DestinationSet createTypePopNotBos(DeviceId deviceId) {
-        return new DestinationSet(DestinationSetType.POP_NOT_BOS, deviceId);
-    }
-
-    /**
-     * Returns a DestinationSet with type SWAP_NOT_BOS.
-     *
-     * @param edgeLabel The edge label to swap with.
-     * @param deviceId The deviceId for this next objective.
-     * @return The DestinationSet of this type.
-     */
-    public static DestinationSet createTypeSwapNotBos(int edgeLabel, DeviceId deviceId) {
-        return new DestinationSet(DestinationSetType.SWAP_NOT_BOS, edgeLabel, deviceId);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/GroupBucketIdentifier.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/GroupBucketIdentifier.java
deleted file mode 100644
index 1c2e1ac..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/GroupBucketIdentifier.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.grouphandler;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import org.onosproject.net.PortNumber;
-
-/**
- * Representation of policy group bucket identifier. Not exposed to
- * the application and only to be used internally.
- */
-public class GroupBucketIdentifier {
-    private int label;
-    private BucketOutputType type;
-    private PortNumber outPort;
-    private PolicyGroupIdentifier outGroup;
-
-    protected enum BucketOutputType {
-        PORT,
-        GROUP
-    }
-
-    protected GroupBucketIdentifier(int label,
-                                    PortNumber outPort) {
-        this.label = label;
-        this.type = BucketOutputType.PORT;
-        this.outPort = checkNotNull(outPort);
-        this.outGroup = null;
-    }
-
-    protected GroupBucketIdentifier(int label,
-                                    PolicyGroupIdentifier outGroup) {
-        this.label = label;
-        this.type = BucketOutputType.GROUP;
-        this.outPort = null;
-        this.outGroup = checkNotNull(outGroup);
-    }
-
-    protected int label() {
-        return this.label;
-    }
-
-    protected BucketOutputType type() {
-        return this.type;
-    }
-
-    protected PortNumber outPort() {
-        return this.outPort;
-    }
-
-    protected PolicyGroupIdentifier outGroup() {
-        return this.outGroup;
-    }
-}
-
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/NextNeighbors.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/NextNeighbors.java
deleted file mode 100644
index eaca1aa..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/NextNeighbors.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.grouphandler;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-import org.onosproject.net.DeviceId;
-
-/**
- * Represents the nexthop information associated with a route-path towards a
- * set of destinations.
- */
-public class NextNeighbors {
-    private final Map<DeviceId, Set<DeviceId>> dstNextHops;
-    private final int nextId;
-
-    /**
-     * Constructor.
-     *
-     * @param dstNextHops map of destinations and the next-hops towards each dest
-     * @param nextId id of nextObjective that manifests the next-hop info
-     */
-    public NextNeighbors(Map<DeviceId, Set<DeviceId>> dstNextHops, int nextId) {
-        this.dstNextHops = dstNextHops;
-        this.nextId = nextId;
-    }
-
-    /**
-     * Returns a map of destinations and the next-hops towards them.
-     *
-     * @return map of destinations and the next-hops towards them
-     */
-    public Map<DeviceId, Set<DeviceId>> dstNextHops() {
-        return dstNextHops;
-    }
-
-    /**
-     * Set of next-hops towards the given destination.
-     *
-     * @param deviceId the destination
-     * @return set of nexthops towards the destination
-     */
-    public Set<DeviceId> nextHops(DeviceId deviceId) {
-        return dstNextHops.get(deviceId);
-    }
-
-    /**
-     * Return the nextId representing the nextObjective towards the next-hops.
-     *
-     * @return nextId representing the nextObjective towards the next-hops
-     */
-    public int nextId() {
-        return nextId;
-    }
-
-    /**
-     * Checks if the given nextHopId is a valid next hop to any one of the
-     * destinations.
-     *
-     * @param nextHopId the deviceId for the next hop
-     * @return true if given next
-     */
-    public boolean containsNextHop(DeviceId nextHopId) {
-        for (Set<DeviceId> nextHops : dstNextHops.values()) {
-            if (nextHops != null && nextHops.contains(nextHopId)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns a set of destinations which have the given nextHopId as one
-     * of the next-hops to that destination.
-     *
-     * @param nextHopId the deviceId for the next hop
-     * @return set of deviceIds that have the given nextHopId as a next-hop
-     *          which could be empty if no destinations were found
-     */
-    public Set<DeviceId> getDstForNextHop(DeviceId nextHopId) {
-        Set<DeviceId> dstSet = new HashSet<>();
-        for (DeviceId dstKey : dstNextHops.keySet()) {
-            if (dstNextHops.get(dstKey).contains(nextHopId)) {
-                dstSet.add(dstKey);
-            }
-        }
-        return dstSet;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof NextNeighbors)) {
-            return false;
-        }
-        NextNeighbors that = (NextNeighbors) o;
-        return (this.nextId == that.nextId) &&
-                this.dstNextHops.equals(that.dstNextHops);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(nextId, dstNextHops);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(this)
-                .add("nextId", nextId)
-                .add("dstNextHops", dstNextHops)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
deleted file mode 100644
index c0935ce..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * 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.grouphandler;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceProperties;
-import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.link.LinkService;
-import org.slf4j.Logger;
-
-/**
- * A module to create group chains based on the specified device
- * ports and label stack to be applied on each port.
- */
-public class PolicyGroupHandler extends DefaultGroupHandler {
-
-    private final Logger log = getLogger(getClass());
-    private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
-
-    /**
-     * Constructs policy group handler.
-     *
-     * @param deviceId device identifier
-     * @param appId application identifier
-     * @param config interface to retrieve the device properties
-     * @param linkService link service object
-     * @param flowObjService flow objective service object
-     * @param srManager segment routing manager
-     */
-    public PolicyGroupHandler(DeviceId deviceId,
-                              ApplicationId appId,
-                              DeviceProperties config,
-                              LinkService linkService,
-                              FlowObjectiveService flowObjService,
-                              SegmentRoutingManager srManager) {
-        super(deviceId, appId, config, linkService, flowObjService, srManager);
-    }
-
-    /**
-     * Creates policy group chain.
-     *
-     * @param id unique identifier associated with the policy group
-     * @param params a list of policy group params
-     * @return policy group identifier
-     */
-    public PolicyGroupIdentifier createPolicyGroupChain(String id,
-                                                        List<PolicyGroupParams> params) {
-        List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
-        for (PolicyGroupParams param: params) {
-            List<PortNumber> ports = param.getPorts();
-            if (ports == null) {
-                log.warn("createPolicyGroupChain in sw {} with wrong "
-                        + "input parameters", deviceId);
-                return null;
-            }
-
-            int labelStackSize = (param.getLabelStack() != null) ?
-                                      param.getLabelStack().size() : 0;
-
-            if (labelStackSize > 1) {
-                for (PortNumber sp : ports) {
-                    PolicyGroupIdentifier previousGroupkey = null;
-                    DeviceId neighbor = portDeviceMap.get(sp);
-                    for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
-                        int label = param.getLabelStack().get(idx);
-                        if (idx == (labelStackSize - 1)) {
-                            // Innermost Group
-                            GroupBucketIdentifier bucketId =
-                                    new GroupBucketIdentifier(label,
-                                                              previousGroupkey);
-                            bucketIds.add(bucketId);
-                        } else if (idx == 0) {
-                            // Outermost Group
-                            List<GroupBucket> outBuckets = new ArrayList<>();
-                            GroupBucketIdentifier bucketId =
-                                    new GroupBucketIdentifier(label, sp);
-                            PolicyGroupIdentifier key = new
-                                    PolicyGroupIdentifier(id,
-                                                          Collections.singletonList(param),
-                                                          Collections.singletonList(bucketId));
-                            MacAddress neighborEthDst;
-                            try {
-                                neighborEthDst = deviceConfig.getDeviceMac(neighbor);
-                            } catch (DeviceConfigNotFoundException e) {
-                                log.warn(e.getMessage()
-                                        + " Skipping createPolicyGroupChain for this label.");
-                                continue;
-                            }
-
-                            TrafficTreatment.Builder tBuilder =
-                                    DefaultTrafficTreatment.builder();
-                            tBuilder.setOutput(sp)
-                                    .setEthDst(neighborEthDst)
-                                    .setEthSrc(nodeMacAddr)
-                                    .pushMpls()
-                                    .setMpls(MplsLabel.mplsLabel(label));
-                            /*outBuckets.add(DefaultGroupBucket.
-                                           createSelectGroupBucket(tBuilder.build()));
-                            GroupDescription desc = new
-                                    DefaultGroupDescription(deviceId,
-                                                            GroupDescription.Type.INDIRECT,
-                                                            new GroupBuckets(outBuckets));
-                            //TODO: BoS*/
-                            previousGroupkey = key;
-                            //groupService.addGroup(desc);
-                            //TODO: Use nextObjective APIs here
-                        } else {
-                            // Intermediate Groups
-                            GroupBucketIdentifier bucketId =
-                                    new GroupBucketIdentifier(label,
-                                                              previousGroupkey);
-                            PolicyGroupIdentifier key = new
-                                    PolicyGroupIdentifier(id,
-                                                          Collections.singletonList(param),
-                                                          Collections.singletonList(bucketId));
-                            // Add to group dependency list
-                            dependentGroups.put(previousGroupkey, key);
-                            previousGroupkey = key;
-                        }
-                    }
-                }
-            } else {
-                int label = -1;
-                if (labelStackSize == 1) {
-                    label = param.getLabelStack().get(0);
-                }
-                for (PortNumber sp : ports) {
-                    GroupBucketIdentifier bucketId =
-                            new GroupBucketIdentifier(label, sp);
-                    bucketIds.add(bucketId);
-                }
-            }
-        }
-        PolicyGroupIdentifier innermostGroupkey = null;
-        if (!bucketIds.isEmpty()) {
-            innermostGroupkey = new
-                    PolicyGroupIdentifier(id,
-                                          params,
-                                          bucketIds);
-            // Add to group dependency list
-            boolean fullyResolved = true;
-            for (GroupBucketIdentifier bucketId:bucketIds) {
-                if (bucketId.type() == BucketOutputType.GROUP) {
-                    dependentGroups.put(bucketId.outGroup(),
-                                        innermostGroupkey);
-                    fullyResolved = false;
-                }
-            }
-
-            if (fullyResolved) {
-                List<GroupBucket> outBuckets = new ArrayList<>();
-                for (GroupBucketIdentifier bucketId : bucketIds) {
-                    DeviceId neighbor = portDeviceMap.
-                            get(bucketId.outPort());
-
-                    MacAddress neighborEthDst;
-                    try {
-                        neighborEthDst = deviceConfig.getDeviceMac(neighbor);
-                    } catch (DeviceConfigNotFoundException e) {
-                        log.warn(e.getMessage()
-                                + " Skipping createPolicyGroupChain for this bucketId.");
-                        continue;
-                    }
-
-                    TrafficTreatment.Builder tBuilder =
-                            DefaultTrafficTreatment.builder();
-                    tBuilder.setOutput(bucketId.outPort())
-                            .setEthDst(neighborEthDst)
-                            .setEthSrc(nodeMacAddr);
-                    if (bucketId.label() != DestinationSet.NO_EDGE_LABEL) {
-                        tBuilder.pushMpls()
-                            .setMpls(MplsLabel.mplsLabel(bucketId.label()));
-                    }
-                    //TODO: BoS
-                    /*outBuckets.add(DefaultGroupBucket.
-                                   createSelectGroupBucket(tBuilder.build()));*/
-                }
-                /*GroupDescription desc = new
-                        DefaultGroupDescription(deviceId,
-                                                GroupDescription.Type.SELECT,
-                                                new GroupBuckets(outBuckets));
-                groupService.addGroup(desc);*/
-                //TODO: Use nextObjective APIs here
-            }
-        }
-        return innermostGroupkey;
-    }
-
-    //TODO: Use nextObjective APIs to handle the group chains
-    /*
-    @Override
-    protected void handleGroupEvent(GroupEvent event) {}
-    */
-
-    /**
-     * Generates policy group key.
-     *
-     * @param id unique identifier associated with the policy group
-     * @param params a list of policy group params
-     * @return policy group identifier
-     */
-    public PolicyGroupIdentifier generatePolicyGroupKey(String id,
-                                   List<PolicyGroupParams> params) {
-        List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
-        for (PolicyGroupParams param: params) {
-            List<PortNumber> ports = param.getPorts();
-            if (ports == null) {
-                log.warn("generateGroupKey in sw {} with wrong "
-                        + "input parameters", deviceId);
-                return null;
-            }
-
-            int labelStackSize = (param.getLabelStack() != null)
-                    ? param.getLabelStack().size() : 0;
-
-            if (labelStackSize > 1) {
-                for (PortNumber sp : ports) {
-                    PolicyGroupIdentifier previousGroupkey = null;
-                    for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
-                        int label = param.getLabelStack().get(idx);
-                        if (idx == (labelStackSize - 1)) {
-                            // Innermost Group
-                            GroupBucketIdentifier bucketId =
-                                    new GroupBucketIdentifier(label,
-                                                              previousGroupkey);
-                            bucketIds.add(bucketId);
-                        } else if (idx == 0) {
-                            // Outermost Group
-                            GroupBucketIdentifier bucketId =
-                                    new GroupBucketIdentifier(label, sp);
-                            PolicyGroupIdentifier key = new
-                                    PolicyGroupIdentifier(id,
-                                                          Collections.singletonList(param),
-                                                          Collections.singletonList(bucketId));
-                            previousGroupkey = key;
-                        } else {
-                            // Intermediate Groups
-                            GroupBucketIdentifier bucketId =
-                                    new GroupBucketIdentifier(label,
-                                                              previousGroupkey);
-                            PolicyGroupIdentifier key = new
-                                    PolicyGroupIdentifier(id,
-                                                          Collections.singletonList(param),
-                                                          Collections.singletonList(bucketId));
-                            previousGroupkey = key;
-                        }
-                    }
-                }
-            } else {
-                int label = -1;
-                if (labelStackSize == 1) {
-                    label = param.getLabelStack().get(0);
-                }
-                for (PortNumber sp : ports) {
-                    GroupBucketIdentifier bucketId =
-                            new GroupBucketIdentifier(label, sp);
-                    bucketIds.add(bucketId);
-                }
-            }
-        }
-        PolicyGroupIdentifier innermostGroupkey = null;
-        if (!bucketIds.isEmpty()) {
-            innermostGroupkey = new
-                    PolicyGroupIdentifier(id,
-                                          params,
-                                          bucketIds);
-        }
-        return innermostGroupkey;
-    }
-
-    /**
-     * Removes policy group chain.
-     *
-     * @param key policy group identifier
-     */
-    public void removeGroupChain(PolicyGroupIdentifier key) {
-        checkArgument(key != null);
-        List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
-        groupsToBeDeleted.add(key);
-
-        Iterator<PolicyGroupIdentifier> it =
-                groupsToBeDeleted.iterator();
-
-        while (it.hasNext()) {
-            PolicyGroupIdentifier innerMostGroupKey = it.next();
-            for (GroupBucketIdentifier bucketId:
-                        innerMostGroupKey.bucketIds()) {
-                if (bucketId.type() != BucketOutputType.GROUP) {
-                    groupsToBeDeleted.add(bucketId.outGroup());
-                }
-            }
-            /*groupService.removeGroup(deviceId,
-                                     getGroupKey(innerMostGroupKey),
-                                     appId);*/
-            //TODO: Use nextObjective APIs here
-            it.remove();
-        }
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupIdentifier.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupIdentifier.java
deleted file mode 100644
index fdc6dea..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupIdentifier.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.grouphandler;
-
-import java.util.List;
-
-/**
- * Representation of policy based group identifiers.
- * Opaque to group handler applications and only the outermost
- * policy group identifier in a chain is visible to the applications.
- */
-public class PolicyGroupIdentifier {
-    private String id;
-    private List<PolicyGroupParams> inputParams;
-    private List<GroupBucketIdentifier> bucketIds;
-
-    /**
-     * Constructs policy group identifier.
-     *
-     * @param id unique identifier associated with the policy group
-     * @param input policy group params associated with this group
-     * @param bucketIds buckets associated with this group
-     */
-    protected PolicyGroupIdentifier(String id,
-                                 List<PolicyGroupParams> input,
-                                 List<GroupBucketIdentifier> bucketIds) {
-        this.id = id;
-        this.inputParams = input;
-        this.bucketIds = bucketIds;
-    }
-
-    /**
-     * Returns the bucket identifier list associated with the policy
-     * group identifier.
-     *
-     * @return list of bucket identifier
-     */
-    protected List<GroupBucketIdentifier> bucketIds() {
-        return this.bucketIds;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = 17;
-        int combinedHash = 0;
-        for (PolicyGroupParams input:inputParams) {
-            combinedHash = combinedHash + input.hashCode();
-        }
-        for (GroupBucketIdentifier bucketId:bucketIds) {
-            combinedHash = combinedHash + bucketId.hashCode();
-        }
-        result = 31 * result + combinedHash;
-
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if (obj instanceof PolicyGroupIdentifier) {
-            PolicyGroupIdentifier that = (PolicyGroupIdentifier) obj;
-            boolean result = this.id.equals(that.id);
-            result = result &&
-                    this.inputParams.containsAll(that.inputParams) &&
-                    that.inputParams.containsAll(this.inputParams);
-            result = result &&
-                    this.bucketIds.containsAll(that.bucketIds) &&
-                    that.bucketIds.containsAll(this.bucketIds);
-            return result;
-        }
-
-        return false;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupParams.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupParams.java
deleted file mode 100644
index 5baf849..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupParams.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.grouphandler;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.List;
-import java.util.Objects;
-
-import org.onosproject.net.PortNumber;
-
-/**
- * Representation of parameters used to create policy based groups.
- */
-public class PolicyGroupParams {
-    private final List<PortNumber> ports;
-    private final List<Integer> labelStack;
-
-    /**
-     * Constructor.
-     *
-     * @param labelStack mpls label stack to be applied on the ports
-     * @param ports ports to be part of the policy group
-     */
-    public PolicyGroupParams(List<Integer> labelStack,
-                             List<PortNumber> ports) {
-        this.ports = checkNotNull(ports);
-        this.labelStack = checkNotNull(labelStack);
-    }
-
-    /**
-     * Returns the ports associated with the policy group params.
-     *
-     * @return list of port numbers
-     */
-    public List<PortNumber> getPorts() {
-        return ports;
-    }
-
-    /**
-     * Returns the label stack associated with the policy group params.
-     *
-     * @return list of integers
-     */
-    public List<Integer> getLabelStack() {
-        return labelStack;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = 17;
-        int combinedHash = 0;
-        for (PortNumber port:ports) {
-            combinedHash = combinedHash + port.hashCode();
-        }
-        combinedHash = combinedHash + Objects.hash(labelStack);
-        result = 31 * result + combinedHash;
-
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if (obj instanceof PolicyGroupParams) {
-            PolicyGroupParams that = (PolicyGroupParams) obj;
-            boolean result = this.labelStack.equals(that.labelStack);
-            result = result &&
-                    this.ports.containsAll(that.ports) &&
-                    that.ports.containsAll(this.ports);
-            return result;
-        }
-
-        return false;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/package-info.java
deleted file mode 100644
index d99f1d1..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Segment routing group handling.
- */
-package org.onosproject.segmentrouting.grouphandler;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreKey.java
deleted file mode 100644
index 6d69984..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreKey.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Key of multicast filtering objective store.
- */
-public class McastFilteringObjStoreKey {
-
-    private final ConnectPoint ingressCP;
-    private final VlanId vlanId;
-    private final boolean isIpv4;
-
-    /**
-     * Constructs the key of multicast filtering objective store.
-     *
-     * @param ingressCP ingress ConnectPoint
-     * @param vlanId vlan id
-     * @param isIpv4 is Ipv4
-     */
-    public McastFilteringObjStoreKey(ConnectPoint ingressCP, VlanId vlanId, boolean isIpv4) {
-        checkNotNull(ingressCP, "connectpoint cannot be null");
-        checkNotNull(vlanId, "vlanid cannot be null");
-        this.ingressCP = ingressCP;
-        this.vlanId = vlanId;
-        this.isIpv4 = isIpv4;
-    }
-
-    // Constructor for serialization
-    private McastFilteringObjStoreKey() {
-        this.ingressCP = null;
-        this.vlanId = null;
-        this.isIpv4 = false;
-    }
-
-
-    /**
-     * Returns the connect point.
-     *
-     * @return ingress connectpoint
-     */
-    public ConnectPoint ingressCP() {
-        return ingressCP;
-    }
-
-    /**
-     * Returns whether the filtering is for ipv4 mcast.
-     *
-     * @return isIpv4
-     */
-    public boolean isIpv4() {
-        return isIpv4;
-    }
-
-    /**
-     * Returns the vlan ID of this key.
-     *
-     * @return vlan ID
-     */
-    public VlanId vlanId() {
-        return vlanId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof McastFilteringObjStoreKey)) {
-            return false;
-        }
-        McastFilteringObjStoreKey that =
-                (McastFilteringObjStoreKey) o;
-        return (Objects.equals(this.ingressCP, that.ingressCP) &&
-                Objects.equals(this.isIpv4, that.isIpv4) &&
-                Objects.equals(this.vlanId, that.vlanId));
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(ingressCP, vlanId, isIpv4);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("ingressCP", ingressCP)
-                .add("isIpv4", isIpv4)
-                .add("vlanId", vlanId)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreSerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreSerializer.java
deleted file mode 100644
index a23fa69..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreSerializer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-/**
- * Custom serializer for {@link McastFilteringObjStoreKey}.
- */
-class McastFilteringObjStoreSerializer extends Serializer<McastFilteringObjStoreKey> {
-
-    /**
-     * Creates {@link McastFilteringObjStoreSerializer} serializer instance.
-     */
-    McastFilteringObjStoreSerializer() {
-        // non-null, immutable
-        super(false, true);
-    }
-
-    @Override
-    public void write(Kryo kryo, Output output, McastFilteringObjStoreKey object) {
-        kryo.writeClassAndObject(output, object.ingressCP());
-        kryo.writeClassAndObject(output, object.vlanId());
-        kryo.writeClassAndObject(output, object.isIpv4());
-    }
-
-    @Override
-    public McastFilteringObjStoreKey read(Kryo kryo, Input input, Class<McastFilteringObjStoreKey> type) {
-        ConnectPoint ingressCP = (ConnectPoint) kryo.readClassAndObject(input);
-        VlanId vlanId = (VlanId) kryo.readClassAndObject(input);
-        boolean isIpv4 = (boolean) kryo.readClassAndObject(input);
-        return new McastFilteringObjStoreKey(ingressCP, vlanId, isIpv4);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
deleted file mode 100644
index 8c4968a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
+++ /dev/null
@@ -1,2055 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.mcast.api.McastEvent;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.mcast.api.McastRouteUpdate;
-import org.onosproject.net.Device;
-import org.onosproject.net.HostId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.ConsistentMultimap;
-import org.onosproject.store.service.DistributedSet;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.Versioned;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.time.Instant;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-
-import static org.onosproject.mcast.api.McastEvent.Type.ROUTE_ADDED;
-import static org.onosproject.mcast.api.McastEvent.Type.ROUTE_REMOVED;
-import static org.onosproject.mcast.api.McastEvent.Type.SOURCES_ADDED;
-import static org.onosproject.mcast.api.McastEvent.Type.SOURCES_REMOVED;
-import static org.onosproject.mcast.api.McastEvent.Type.SINKS_ADDED;
-import static org.onosproject.mcast.api.McastEvent.Type.SINKS_REMOVED;
-
-import static org.onosproject.segmentrouting.mcast.McastRole.EGRESS;
-import static org.onosproject.segmentrouting.mcast.McastRole.INGRESS;
-import static org.onosproject.segmentrouting.mcast.McastRole.TRANSIT;
-
-/**
- * Handles Multicast related events.
- */
-public class McastHandler {
-    // Internal elements
-    private static final Logger log = LoggerFactory.getLogger(McastHandler.class);
-    private final SegmentRoutingManager srManager;
-    private final McastUtils mcastUtils;
-    private final ConsistentMap<McastStoreKey, NextObjective> mcastNextObjStore;
-    private final ConsistentMap<McastRoleStoreKey, McastRole> mcastRoleStore;
-    private final ConsistentMultimap<McastPathStoreKey, List<Link>> mcastPathStore;
-    private final DistributedSet<McastFilteringObjStoreKey> mcastFilteringObjStore;
-    // Stability threshold for Mcast. Seconds
-    private static final long MCAST_STABLITY_THRESHOLD = 5;
-    // Verify interval for Mcast bucket corrector
-    private static final long MCAST_VERIFY_INTERVAL = 30;
-    // Max verify that can be processed at the same time
-    private static final int MAX_VERIFY_ON_FLIGHT = 10;
-    // Last change done
-    private AtomicReference<Instant> lastMcastChange = new AtomicReference<>(Instant.now());
-    // Last bucker corrector execution
-    private AtomicReference<Instant> lastBktCorrExecution = new AtomicReference<>(Instant.now());
-    // Executors for mcast bucket corrector and for the events
-    private ScheduledExecutorService mcastCorrector
-            = newScheduledThreadPool(1, groupedThreads("onos", "m-corrector", log));
-    private ScheduledExecutorService mcastWorker
-            = newScheduledThreadPool(1, groupedThreads("onos", "m-worker-%d", log));
-
-    /**
-     * Constructs the McastEventHandler.
-     *
-     * @param srManager Segment Routing manager
-     */
-    public McastHandler(SegmentRoutingManager srManager) {
-        ApplicationId coreAppId = srManager.coreService.getAppId(CoreService.CORE_APP_NAME);
-        this.srManager = srManager;
-        KryoNamespace.Builder mcastKryo = new KryoNamespace.Builder()
-                .register(KryoNamespaces.API)
-                .register(new McastStoreKeySerializer(), McastStoreKey.class);
-        mcastNextObjStore = srManager.storageService
-                .<McastStoreKey, NextObjective>consistentMapBuilder()
-                .withName("onos-mcast-nextobj-store")
-                .withSerializer(Serializer.using(mcastKryo.build("McastHandler-NextObj")))
-                .build();
-        mcastKryo = new KryoNamespace.Builder()
-                .register(KryoNamespaces.API)
-                .register(new McastRoleStoreKeySerializer(), McastRoleStoreKey.class)
-                .register(McastRole.class);
-        mcastRoleStore = srManager.storageService
-                .<McastRoleStoreKey, McastRole>consistentMapBuilder()
-                .withName("onos-mcast-role-store")
-                .withSerializer(Serializer.using(mcastKryo.build("McastHandler-Role")))
-                .build();
-        mcastKryo = new KryoNamespace.Builder()
-                .register(KryoNamespaces.API)
-                .register(new McastFilteringObjStoreSerializer(), McastFilteringObjStoreKey.class);
-        mcastFilteringObjStore = srManager.storageService
-                .<McastFilteringObjStoreKey>setBuilder()
-                .withName("onos-mcast-filtering-store")
-                .withSerializer(Serializer.using(mcastKryo.build("McastHandler-FilteringObj")))
-                .build()
-                .asDistributedSet();
-        mcastKryo = new KryoNamespace.Builder()
-                .register(KryoNamespaces.API)
-                .register(new McastPathStoreKeySerializer(), McastPathStoreKey.class);
-        mcastPathStore = srManager.storageService
-                .<McastPathStoreKey, List<Link>>consistentMultimapBuilder()
-                .withName("onos-mcast-path-store")
-                .withSerializer(Serializer.using(mcastKryo.build("McastHandler-Path")))
-                .build();
-        mcastUtils = new McastUtils(srManager, coreAppId, log);
-        // Init the executor for the buckets corrector
-        mcastCorrector.scheduleWithFixedDelay(new McastBucketCorrector(), 10,
-                                              MCAST_VERIFY_INTERVAL, TimeUnit.SECONDS);
-    }
-
-    /**
-     * Determines if mcast in the network has been stable in the last
-     * MCAST_STABLITY_THRESHOLD seconds, by comparing the current time
-     * to the last mcast change timestamp.
-     *
-     * @return true if stable
-     */
-    private boolean isMcastStable() {
-        long last = (long) (lastMcastChange.get().toEpochMilli() / 1000.0);
-        long now = (long) (Instant.now().toEpochMilli() / 1000.0);
-        log.trace("Multicast stable since {}s", now - last);
-        return (now - last) > MCAST_STABLITY_THRESHOLD;
-    }
-
-    /**
-     * Assures there are always MCAST_VERIFY_INTERVAL seconds between each execution,
-     * by comparing the current time with the last corrector execution.
-     *
-     * @return true if stable
-     */
-    private boolean wasBktCorrRunning() {
-        long last = (long) (lastBktCorrExecution.get().toEpochMilli() / 1000.0);
-        long now = (long) (Instant.now().toEpochMilli() / 1000.0);
-        log.trace("McastBucketCorrector executed {}s ago", now - last);
-        return (now - last) < MCAST_VERIFY_INTERVAL;
-    }
-
-    /**
-     * Read initial multicast configuration from mcast store.
-     */
-    public void init() {
-        mcastWorker.execute(this::initInternal);
-    }
-
-    private void initInternal() {
-        srManager.multicastRouteService.getRoutes().forEach(mcastRoute -> {
-            lastMcastChange.set(Instant.now());
-            log.debug("Init group {}", mcastRoute.group());
-            if (!mcastUtils.isLeader(mcastRoute.group())) {
-                log.debug("Skip {} due to lack of leadership", mcastRoute.group());
-                return;
-            }
-            McastRouteData mcastRouteData = srManager.multicastRouteService.routeData(mcastRoute);
-            // For each source process the mcast tree
-            srManager.multicastRouteService.sources(mcastRoute).forEach(source -> {
-                McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastRoute.group(), source);
-                Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
-                        mcastPathStore.get(pathStoreKey), Lists.newArrayList());
-                Map<ConnectPoint, List<ConnectPoint>> mcastPaths = buildMcastPaths(storedPaths, mcastRoute.group(),
-                                                                                   source);
-                // Get all the sinks and process them
-                Set<ConnectPoint> sinks = processSinksToBeAdded(source, mcastRoute.group(),
-                                                                mcastRouteData.sinks());
-                // Filter out all the working sinks, we do not want to move them
-                // TODO we need a better way to distinguish flows coming from different sources
-                sinks = sinks.stream()
-                        .filter(sink -> !mcastPaths.containsKey(sink) ||
-                                !isSinkForSource(mcastRoute.group(), sink, source))
-                        .collect(Collectors.toSet());
-                if (sinks.isEmpty()) {
-                    log.debug("Skip {} for source {} nothing to do", mcastRoute.group(), source);
-                    return;
-                }
-                Map<ConnectPoint, List<Path>> mcasTree = mcastUtils.computeSinkMcastTree(mcastRoute.group(),
-                                                                                         source.deviceId(), sinks);
-                mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink, mcastRoute.group(),
-                                                                             null));
-            });
-        });
-    }
-
-    /**
-     * Clean up when deactivating the application.
-     */
-    public void terminate() {
-        mcastCorrector.shutdown();
-        mcastWorker.shutdown();
-        mcastNextObjStore.destroy();
-        mcastRoleStore.destroy();
-        mcastFilteringObjStore.destroy();
-        mcastPathStore.destroy();
-        mcastUtils.terminate();
-        log.info("Terminated");
-    }
-
-    /**
-     * Processes the SOURCE_ADDED, SOURCE_UPDATED, SINK_ADDED,
-     * SINK_REMOVED, ROUTE_ADDED and ROUTE_REMOVED events.
-     *
-     * @param event the multicast event to be processed
-     */
-    public void processMcastEvent(McastEvent event) {
-        mcastWorker.execute(() -> processMcastEventInternal(event));
-    }
-
-    private void processMcastEventInternal(McastEvent event) {
-        lastMcastChange.set(Instant.now());
-        // Current subject is null, for ROUTE_REMOVED events
-        final McastRouteUpdate mcastUpdate = event.subject();
-        final McastRouteUpdate mcastPrevUpdate = event.prevSubject();
-        IpAddress mcastIp = mcastPrevUpdate.route().group();
-        Set<ConnectPoint> prevSinks = mcastPrevUpdate.sinks()
-                .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
-        Set<ConnectPoint> prevSources = mcastPrevUpdate.sources()
-                .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
-        Set<ConnectPoint> sources;
-        // Events handling
-        if (event.type() == ROUTE_ADDED) {
-            processRouteAddedInternal(mcastUpdate.route().group());
-        } else if (event.type() == ROUTE_REMOVED) {
-            processRouteRemovedInternal(prevSources, mcastIp);
-        } else if (event.type() == SOURCES_ADDED) {
-            // Current subject and prev just differ for the source connect points
-            sources = mcastUpdate.sources()
-                    .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
-            Set<ConnectPoint> sourcesToBeAdded = Sets.difference(sources, prevSources);
-            processSourcesAddedInternal(sourcesToBeAdded, mcastIp, mcastUpdate.sinks());
-        } else if (event.type() == SOURCES_REMOVED) {
-            // Current subject and prev just differ for the source connect points
-            sources = mcastUpdate.sources()
-                    .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
-            Set<ConnectPoint> sourcesToBeRemoved = Sets.difference(prevSources, sources);
-            processSourcesRemovedInternal(sourcesToBeRemoved, sources, mcastIp, mcastUpdate.sinks());
-        } else if (event.type() == SINKS_ADDED) {
-            processSinksAddedInternal(prevSources, mcastIp, mcastUpdate.sinks(), prevSinks);
-        } else if (event.type() == SINKS_REMOVED) {
-            processSinksRemovedInternal(prevSources, mcastIp, mcastUpdate.sinks(), mcastPrevUpdate.sinks());
-        } else {
-            log.warn("Event {} not handled", event);
-        }
-    }
-
-    /**
-     * Process the SOURCES_ADDED event.
-     *
-     * @param sources the sources connect point
-     * @param mcastIp the group address
-     * @param sinks the sinks connect points
-     */
-    private void processSourcesAddedInternal(Set<ConnectPoint> sources, IpAddress mcastIp,
-                                             Map<HostId, Set<ConnectPoint>> sinks) {
-        lastMcastChange.set(Instant.now());
-        log.info("Processing sources added {} for group {}", sources, mcastIp);
-        if (!mcastUtils.isLeader(mcastIp)) {
-            log.debug("Skip {} due to lack of leadership", mcastIp);
-            return;
-        }
-        if (sources.isEmpty()) {
-            log.debug("Skip {} due to empty sources to be added", mcastIp);
-            return;
-        }
-        sources.forEach(source -> {
-            Set<ConnectPoint> sinksToBeAdded = processSinksToBeAdded(source, mcastIp, sinks);
-            Map<ConnectPoint, List<Path>> mcasTree = mcastUtils.computeSinkMcastTree(mcastIp, source.deviceId(),
-                                                                                     sinksToBeAdded);
-            mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink, mcastIp, paths));
-        });
-    }
-
-    /**
-     * Process the SOURCES_REMOVED event.
-     *
-     * @param sourcesToBeRemoved the source connect points to be removed
-     * @param remainingSources the remainig source connect points
-     * @param mcastIp the group address
-     * @param sinks the sinks connect points
-     */
-    private void processSourcesRemovedInternal(Set<ConnectPoint> sourcesToBeRemoved,
-                                               Set<ConnectPoint> remainingSources,
-                                               IpAddress mcastIp,
-                                               Map<HostId, Set<ConnectPoint>> sinks) {
-        lastMcastChange.set(Instant.now());
-        log.info("Processing sources removed {} for group {}", sourcesToBeRemoved, mcastIp);
-        if (!mcastUtils.isLeader(mcastIp)) {
-            log.debug("Skip {} due to lack of leadership", mcastIp);
-            return;
-        }
-        if (remainingSources.isEmpty()) {
-            log.debug("There are no more sources for {}", mcastIp);
-            processRouteRemovedInternal(sourcesToBeRemoved, mcastIp);
-            return;
-        }
-        // Let's heal the trees
-        Set<Link> notAffectedLinks = Sets.newHashSet();
-        Map<ConnectPoint, Set<Link>> affectedLinks = Maps.newHashMap();
-        Map<ConnectPoint, Set<ConnectPoint>> candidateSinks = Maps.newHashMap();
-        Set<ConnectPoint> totalSources = Sets.newHashSet(sourcesToBeRemoved);
-        totalSources.addAll(remainingSources);
-        // Calculate all the links used by the sources and the current sinks
-        totalSources.forEach(source -> {
-            Set<ConnectPoint> currentSinks = sinks.values()
-                    .stream().flatMap(Collection::stream)
-                    .filter(sink -> isSinkForSource(mcastIp, sink, source))
-                    .collect(Collectors.toSet());
-            candidateSinks.put(source, currentSinks);
-            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-            Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
-                    mcastPathStore.get(pathStoreKey), Lists.newArrayList());
-            currentSinks.forEach(currentSink -> {
-                Optional<? extends List<Link>> currentPath = mcastUtils.getStoredPath(currentSink.deviceId(),
-                                                                                      storedPaths);
-                if (currentPath.isPresent()) {
-                    if (!sourcesToBeRemoved.contains(source)) {
-                        notAffectedLinks.addAll(currentPath.get());
-                    } else {
-                        affectedLinks.compute(source, (k, v) -> {
-                           v = v == null ? Sets.newHashSet() : v;
-                           v.addAll(currentPath.get());
-                           return v;
-                        });
-                    }
-                }
-            });
-        });
-        // Clean transit links
-        affectedLinks.forEach((source, currentCandidateLinks) -> {
-            Set<Link> linksToBeRemoved = Sets.difference(currentCandidateLinks, notAffectedLinks)
-                    .immutableCopy();
-            if (!linksToBeRemoved.isEmpty()) {
-                currentCandidateLinks.forEach(link -> {
-                    DeviceId srcLink = link.src().deviceId();
-                    // Remove ports only on links to be removed
-                    if (linksToBeRemoved.contains(link)) {
-                        removePortFromDevice(link.src().deviceId(), link.src().port(), mcastIp,
-                                             mcastUtils.assignedVlan(srcLink.equals(source.deviceId()) ?
-                                                                             source : null));
-                    }
-                    // Remove role on the candidate links
-                    mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, srcLink, source));
-                });
-            }
-        });
-        // Clean ingress and egress
-        sourcesToBeRemoved.forEach(source -> {
-            Set<ConnectPoint> currentSinks = candidateSinks.get(source);
-            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-            currentSinks.forEach(currentSink -> {
-                VlanId assignedVlan = mcastUtils.assignedVlan(source.deviceId().equals(currentSink.deviceId()) ?
-                                                                      source : null);
-                // Sinks co-located with the source
-                if (source.deviceId().equals(currentSink.deviceId())) {
-                    if (source.port().equals(currentSink.port())) {
-                        log.warn("Skip {} since sink {} is on the same port of source {}. Abort",
-                                 mcastIp, currentSink, source);
-                        return;
-                    }
-                    // We need to check against the other sources and if it is
-                    // necessary remove the port from the device - no overlap
-                    Set<VlanId> otherVlans = remainingSources.stream()
-                            // Only sources co-located and having this sink
-                            .filter(remainingSource -> remainingSource.deviceId()
-                                    .equals(source.deviceId()) && candidateSinks.get(remainingSource)
-                                    .contains(currentSink))
-                            .map(remainingSource -> mcastUtils.assignedVlan(
-                                    remainingSource.deviceId().equals(currentSink.deviceId()) ?
-                                            remainingSource : null)).collect(Collectors.toSet());
-                    if (!otherVlans.contains(assignedVlan)) {
-                        removePortFromDevice(currentSink.deviceId(), currentSink.port(),
-                                             mcastIp, assignedVlan);
-                    }
-                    mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(),
-                                                                source));
-                    return;
-                }
-                Set<VlanId> otherVlans = remainingSources.stream()
-                        .filter(remainingSource -> candidateSinks.get(remainingSource)
-                                .contains(currentSink))
-                        .map(remainingSource -> mcastUtils.assignedVlan(
-                                remainingSource.deviceId().equals(currentSink.deviceId()) ?
-                                        remainingSource : null)).collect(Collectors.toSet());
-                // Sinks on other leaves
-                if (!otherVlans.contains(assignedVlan)) {
-                    removePortFromDevice(currentSink.deviceId(), currentSink.port(),
-                                         mcastIp, assignedVlan);
-                }
-                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(),
-                                                            source));
-            });
-            // Clean the mcast paths
-            mcastPathStore.removeAll(pathStoreKey);
-        });
-    }
-
-    /**
-     * Process the ROUTE_ADDED event.
-     *
-     * @param mcastIp the group address
-     */
-    private void processRouteAddedInternal(IpAddress mcastIp) {
-        lastMcastChange.set(Instant.now());
-        log.info("Processing route added for Multicast group {}", mcastIp);
-        // Just elect a new leader
-        mcastUtils.isLeader(mcastIp);
-    }
-
-    /**
-     * Removes the entire mcast tree related to this group.
-     * @param sources the source connect points
-     * @param mcastIp multicast group IP address
-     */
-    private void processRouteRemovedInternal(Set<ConnectPoint> sources, IpAddress mcastIp) {
-        lastMcastChange.set(Instant.now());
-        log.info("Processing route removed for group {}", mcastIp);
-        if (!mcastUtils.isLeader(mcastIp)) {
-            log.debug("Skip {} due to lack of leadership", mcastIp);
-            mcastUtils.withdrawLeader(mcastIp);
-            return;
-        }
-        sources.forEach(source -> {
-            // Find out the ingress, transit and egress device of the affected group
-            DeviceId ingressDevice = getDevice(mcastIp, INGRESS, source)
-                    .stream().findFirst().orElse(null);
-            Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT, source);
-            Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS, source);
-            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-            // If there are no egress and transit devices, sinks could be only on the ingress
-            if (!egressDevices.isEmpty()) {
-                egressDevices.forEach(deviceId -> {
-                    removeGroupFromDevice(deviceId, mcastIp, mcastUtils.assignedVlan(null));
-                    mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, deviceId, source));
-                });
-            }
-            if (!transitDevices.isEmpty()) {
-                transitDevices.forEach(deviceId -> {
-                    removeGroupFromDevice(deviceId, mcastIp, mcastUtils.assignedVlan(null));
-                    mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, deviceId, source));
-                });
-            }
-            if (ingressDevice != null) {
-                removeGroupFromDevice(ingressDevice, mcastIp, mcastUtils.assignedVlan(source));
-                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, ingressDevice, source));
-            }
-            // Clean the mcast paths
-            mcastPathStore.removeAll(pathStoreKey);
-        });
-        // Finally, withdraw the leadership
-        mcastUtils.withdrawLeader(mcastIp);
-    }
-
-    /**
-     * Process sinks to be removed.
-     *
-     * @param sources the source connect points
-     * @param mcastIp the ip address of the group
-     * @param newSinks the new sinks to be processed
-     * @param prevSinks the previous sinks
-     */
-    private void processSinksRemovedInternal(Set<ConnectPoint> sources, IpAddress mcastIp,
-                                             Map<HostId, Set<ConnectPoint>> newSinks,
-                                             Map<HostId, Set<ConnectPoint>> prevSinks) {
-        lastMcastChange.set(Instant.now());
-        log.info("Processing sinks removed for group {} and for sources {}",
-                  mcastIp, sources);
-        if (!mcastUtils.isLeader(mcastIp)) {
-            log.debug("Skip {} due to lack of leadership", mcastIp);
-            return;
-        }
-        Map<ConnectPoint, Map<ConnectPoint, Optional<? extends List<Link>>>> treesToBeRemoved = Maps.newHashMap();
-        Map<ConnectPoint, Set<ConnectPoint>> treesToBeAdded = Maps.newHashMap();
-        Set<Link> goodLinks = Sets.newHashSet();
-        Map<ConnectPoint, Set<DeviceId>> goodDevicesBySource = Maps.newHashMap();
-        sources.forEach(source -> {
-            // Save the path associated to the sinks to be removed
-            Set<ConnectPoint> sinksToBeRemoved = processSinksToBeRemoved(mcastIp, prevSinks,
-                                                                         newSinks, source);
-            Map<ConnectPoint, Optional<? extends List<Link>>> treeToBeRemoved = Maps.newHashMap();
-            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-            Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
-                    mcastPathStore.get(pathStoreKey), Lists.newArrayList());
-            sinksToBeRemoved.forEach(sink -> treeToBeRemoved.put(sink, mcastUtils.getStoredPath(sink.deviceId(),
-                                                                                                storedPaths)));
-            treesToBeRemoved.put(source, treeToBeRemoved);
-            // Save the good links and good devices
-            Set<DeviceId> goodDevices = Sets.newHashSet();
-            Set<DeviceId> totalDevices = Sets.newHashSet(getDevice(mcastIp, EGRESS, source));
-            totalDevices.addAll(getDevice(mcastIp, INGRESS, source));
-            Set<ConnectPoint> notAffectedSinks = Sets.newHashSet();
-            // Compute good sinks
-            totalDevices.forEach(device -> {
-                Set<ConnectPoint> sinks = getSinks(mcastIp, device, source);
-                notAffectedSinks.addAll(Sets.difference(sinks, sinksToBeRemoved));
-            });
-            // Compute good paths and good devices
-            notAffectedSinks.forEach(notAffectedSink -> {
-                Optional<? extends List<Link>> notAffectedPath = mcastUtils.getStoredPath(notAffectedSink.deviceId(),
-                                                                                          storedPaths);
-                if (notAffectedPath.isPresent()) {
-                    List<Link> goodPath = notAffectedPath.get();
-                    goodLinks.addAll(goodPath);
-                    goodPath.forEach(link -> goodDevices.add(link.src().deviceId()));
-                } else {
-                    goodDevices.add(notAffectedSink.deviceId());
-                }
-            });
-            goodDevicesBySource.compute(source, (k, v) -> {
-                v = v == null ? Sets.newHashSet() : v;
-                v.addAll(goodDevices);
-                return v;
-            });
-            // Recover the dual-homed sinks
-            Set<ConnectPoint> sinksToBeRecovered = processSinksToBeRecovered(mcastIp, newSinks,
-                                                                             prevSinks, source);
-            treesToBeAdded.put(source, sinksToBeRecovered);
-        });
-        // Remove the sinks taking into account the multiple sources and the original paths
-        treesToBeRemoved.forEach((source, tree) ->
-            tree.forEach((sink, path) -> processSinkRemovedInternal(source, sink, mcastIp, path,
-                                                                    goodLinks, goodDevicesBySource.get(source))));
-        // Add new sinks according to the recovery procedure
-        treesToBeAdded.forEach((source, sinks) ->
-            sinks.forEach(sink -> processSinkAddedInternal(source, sink, mcastIp, null)));
-    }
-
-    /**
-     * Removes a path from source to sink for given multicast group.
-     *
-     * @param source connect point of the multicast source
-     * @param sink connection point of the multicast sink
-     * @param mcastIp multicast group IP address
-     * @param mcastPath path associated to the sink
-     * @param usedLinks links used by the other sinks
-     * @param usedDevices devices used by other sinks
-     */
-    private void processSinkRemovedInternal(ConnectPoint source, ConnectPoint sink,
-                                            IpAddress mcastIp, Optional<? extends List<Link>> mcastPath,
-                                            Set<Link> usedLinks, Set<DeviceId> usedDevices) {
-
-        log.info("Used links {}", usedLinks);
-        log.info("Used devices {}", usedDevices);
-
-        lastMcastChange.set(Instant.now());
-        log.info("Processing sink removed {} for group {} and for source {}", sink, mcastIp, source);
-        boolean isLast;
-        // When source and sink are on the same device
-        if (source.deviceId().equals(sink.deviceId())) {
-            // Source and sink are on even the same port. There must be something wrong.
-            if (source.port().equals(sink.port())) {
-                log.warn("Skip {} since sink {} is on the same port of source {}. Abort", mcastIp, sink, source);
-                return;
-            }
-            isLast = removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(source));
-            if (isLast) {
-                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, sink.deviceId(), source));
-            }
-            return;
-        }
-        // Process the egress device
-        isLast = removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(null));
-        if (isLast) {
-            mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, sink.deviceId(), source));
-        }
-        // If this is the last sink on the device, also update upstream
-        if (mcastPath.isPresent()) {
-            List<Link> links = Lists.newArrayList(mcastPath.get());
-            if (isLast) {
-                // Clean the path
-                McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-                mcastPathStore.remove(pathStoreKey, mcastPath.get());
-                Collections.reverse(links);
-                for (Link link : links) {
-                    // If nobody is using the port remove
-                    if (!usedLinks.contains(link)) {
-                        removePortFromDevice(link.src().deviceId(), link.src().port(), mcastIp,
-                          mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
-                    }
-                    // If nobody is using the device
-                    if (!usedDevices.contains(link.src().deviceId())) {
-                        mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, link.src().deviceId(), source));
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Process sinks to be added.
-     *
-     * @param sources the source connect points
-     * @param mcastIp the group IP
-     * @param newSinks the new sinks to be processed
-     * @param allPrevSinks all previous sinks
-     */
-    private void processSinksAddedInternal(Set<ConnectPoint> sources, IpAddress mcastIp,
-                                           Map<HostId, Set<ConnectPoint>> newSinks,
-                                           Set<ConnectPoint> allPrevSinks) {
-        lastMcastChange.set(Instant.now());
-        log.info("Processing sinks added for group {} and for sources {}", mcastIp, sources);
-        if (!mcastUtils.isLeader(mcastIp)) {
-            log.debug("Skip {} due to lack of leadership", mcastIp);
-            return;
-        }
-        sources.forEach(source -> {
-            Set<ConnectPoint> sinksToBeAdded = processSinksToBeAdded(source, mcastIp, newSinks);
-            sinksToBeAdded = Sets.difference(sinksToBeAdded, allPrevSinks);
-            sinksToBeAdded.forEach(sink -> processSinkAddedInternal(source, sink, mcastIp, null));
-        });
-    }
-
-    /**
-     * Establishes a path from source to sink for given multicast group.
-     *
-     * @param source connect point of the multicast source
-     * @param sink connection point of the multicast sink
-     * @param mcastIp multicast group IP address
-     */
-    private void processSinkAddedInternal(ConnectPoint source, ConnectPoint sink,
-                                          IpAddress mcastIp, List<Path> allPaths) {
-        lastMcastChange.set(Instant.now());
-        log.info("Processing sink added {} for group {} and for source {}", sink, mcastIp, source);
-        // Process the ingress device
-        McastFilteringObjStoreKey mcastFilterObjStoreKey = new McastFilteringObjStoreKey(source,
-                                                           mcastUtils.assignedVlan(source), mcastIp.isIp4());
-        addFilterToDevice(mcastFilterObjStoreKey, mcastIp, INGRESS);
-        if (source.deviceId().equals(sink.deviceId())) {
-            if (source.port().equals(sink.port())) {
-                log.warn("Skip {} since sink {} is on the same port of source {}. Abort",
-                         mcastIp, sink, source);
-                return;
-            }
-            addPortToDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(source));
-            mcastRoleStore.put(new McastRoleStoreKey(mcastIp, sink.deviceId(), source), INGRESS);
-            return;
-        }
-        // Find a path. If present, create/update groups and flows for each hop
-        Optional<Path> mcastPath = getPath(source.deviceId(), sink.deviceId(), mcastIp, allPaths);
-        if (mcastPath.isPresent()) {
-            List<Link> links = mcastPath.get().links();
-            McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-            // Setup mcast role for ingress
-            mcastRoleStore.put(new McastRoleStoreKey(mcastIp, source.deviceId(), source), INGRESS);
-            // Setup properly the transit forwarding
-            links.forEach(link -> {
-                addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp,
-                                mcastUtils.assignedVlan(link.src().deviceId()
-                                                                .equals(source.deviceId()) ? source : null));
-                McastFilteringObjStoreKey filteringKey = new McastFilteringObjStoreKey(link.dst(),
-                                                                   mcastUtils.assignedVlan(null), mcastIp.isIp4());
-                addFilterToDevice(filteringKey, mcastIp, null);
-            });
-            // Setup mcast role for the transit
-            links.stream()
-                    .filter(link -> !link.dst().deviceId().equals(sink.deviceId()))
-                    .forEach(link -> mcastRoleStore.put(new McastRoleStoreKey(mcastIp, link.dst().deviceId(),
-                                                                              source), TRANSIT));
-            // Process the egress device
-            addPortToDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(null));
-            // Setup mcast role for egress
-            mcastRoleStore.put(new McastRoleStoreKey(mcastIp, sink.deviceId(), source), EGRESS);
-            // Store the used path
-            mcastPathStore.put(pathStoreKey, links);
-        } else {
-            log.warn("Unable to find a path from {} to {}. Abort sinkAdded", source.deviceId(), sink.deviceId());
-        }
-    }
-
-    /**
-     * Processes the PORT_UPDATED event.
-     *
-     * @param affectedDevice Affected device
-     * @param affectedPort Affected port
-     */
-    public void processPortUpdate(Device affectedDevice, Port affectedPort) {
-        mcastWorker.execute(() -> processPortUpdateInternal(affectedDevice, affectedPort));
-    }
-
-    private void processPortUpdateInternal(Device affectedDevice, Port affectedPort) {
-        // Clean the filtering obj store. Edge port case.
-        lastMcastChange.set(Instant.now());
-        ConnectPoint portDown = new ConnectPoint(affectedDevice.id(), affectedPort.number());
-        if (!affectedPort.isEnabled()) {
-            log.info("Processing port down {}", portDown);
-            updateFilterObjStoreByPort(portDown);
-        }
-    }
-
-    /**
-     * Processes the LINK_DOWN event.
-     *
-     * @param linkDown Link that is going down
-     */
-    public void processLinkDown(Link linkDown) {
-        mcastWorker.execute(() -> processLinkDownInternal(linkDown));
-    }
-
-    private void processLinkDownInternal(Link linkDown) {
-        // Get mcast groups affected by the link going down
-        Set<IpAddress> affectedGroups = getAffectedGroups(linkDown);
-        log.info("Processing link down {} for groups {}", linkDown, affectedGroups);
-        affectedGroups.forEach(mcastIp -> {
-            lastMcastChange.set(Instant.now());
-            log.debug("Processing link down {} for group {}", linkDown, mcastIp);
-            recoverFailure(mcastIp, linkDown);
-        });
-    }
-
-    /**
-     * Process the DEVICE_DOWN event.
-     *
-     * @param deviceDown device going down
-     */
-    public void processDeviceDown(DeviceId deviceDown) {
-        mcastWorker.execute(() -> processDeviceDownInternal(deviceDown));
-    }
-
-    private void processDeviceDownInternal(DeviceId deviceDown) {
-        // Get the mcast groups affected by the device going down
-        Set<IpAddress> affectedGroups = getAffectedGroups(deviceDown);
-        log.info("Processing device down {} for groups {}", deviceDown, affectedGroups);
-        updateFilterObjStoreByDevice(deviceDown);
-        affectedGroups.forEach(mcastIp -> {
-            lastMcastChange.set(Instant.now());
-            log.debug("Processing device down {} for group {}", deviceDown, mcastIp);
-            recoverFailure(mcastIp, deviceDown);
-        });
-    }
-
-    /**
-     * General failure recovery procedure.
-     *
-     * @param mcastIp the group to recover
-     * @param failedElement the failed element
-     */
-    private void recoverFailure(IpAddress mcastIp, Object failedElement) {
-        // Do not proceed if we are not the leaders
-        if (!mcastUtils.isLeader(mcastIp)) {
-            log.debug("Skip {} due to lack of leadership", mcastIp);
-            return;
-        }
-        // Skip if it is not an infra failure
-        Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT);
-        if (!mcastUtils.isInfraFailure(transitDevices, failedElement)) {
-            log.debug("Skip {} not an infrastructure failure", mcastIp);
-            return;
-        }
-        // Do not proceed if the sources of this group are missing
-        Set<ConnectPoint> sources = getSources(mcastIp);
-        if (sources.isEmpty()) {
-            log.warn("Missing sources for group {}", mcastIp);
-            return;
-        }
-        // Get all the paths, affected paths, good links and good devices
-        Set<List<Link>> storedPaths = getStoredPaths(mcastIp);
-        Set<List<Link>> affectedPaths = mcastUtils.getAffectedPaths(storedPaths, failedElement);
-        Set<Link> goodLinks = Sets.newHashSet();
-        Map<DeviceId, Set<DeviceId>> goodDevicesBySource = Maps.newHashMap();
-        Map<DeviceId, Set<ConnectPoint>> processedSourcesByEgress = Maps.newHashMap();
-        Sets.difference(storedPaths, affectedPaths).forEach(goodPath -> {
-            goodLinks.addAll(goodPath);
-            DeviceId srcDevice = goodPath.get(0).src().deviceId();
-            Set<DeviceId> goodDevices = Sets.newHashSet();
-            goodPath.forEach(link -> goodDevices.add(link.src().deviceId()));
-            goodDevicesBySource.compute(srcDevice, (k, v) -> {
-                v = v == null ? Sets.newHashSet() : v;
-                v.addAll(goodDevices);
-                return v;
-            });
-        });
-        affectedPaths.forEach(affectedPath -> {
-            // TODO remove
-            log.info("Good links {}", goodLinks);
-            // TODO remove
-            log.info("Good devices {}", goodDevicesBySource);
-            // TODO trace
-            log.info("Healing the path {}", affectedPath);
-            DeviceId srcDevice = affectedPath.get(0).src().deviceId();
-            DeviceId dstDevice = affectedPath.get(affectedPath.size() - 1).dst().deviceId();
-            // Fix in one shot multiple sources
-            Set<ConnectPoint> affectedSources = sources.stream()
-                    .filter(device -> device.deviceId().equals(srcDevice))
-                    .collect(Collectors.toSet());
-            Set<ConnectPoint> processedSources = processedSourcesByEgress.getOrDefault(dstDevice,
-                                                                                       Collections.emptySet());
-            Optional<Path> alternativePath = getPath(srcDevice, dstDevice, mcastIp, null);
-            // If an alternative is possible go ahead
-            if (alternativePath.isPresent()) {
-                // TODO trace
-                log.info("Alternative path {}", alternativePath.get().links());
-            } else {
-                // Otherwise try to come up with an alternative
-                // TODO trace
-                log.info("No alternative path");
-                Set<ConnectPoint> notAffectedSources = Sets.difference(sources, affectedSources);
-                Set<ConnectPoint> remainingSources = Sets.difference(notAffectedSources, processedSources);
-                alternativePath = recoverSinks(dstDevice, mcastIp, affectedSources, remainingSources);
-                processedSourcesByEgress.compute(dstDevice, (k, v) -> {
-                    v = v == null ? Sets.newHashSet() : v;
-                    v.addAll(affectedSources);
-                    return v;
-                });
-            }
-            // Recover from the failure if possible
-            Optional<Path> finalPath = alternativePath;
-            affectedSources.forEach(affectedSource -> {
-                // Update the mcastPath store
-                McastPathStoreKey mcastPathStoreKey = new McastPathStoreKey(mcastIp, affectedSource);
-                // Verify if there are local sinks
-                Set<DeviceId> localSinks = getSinks(mcastIp, srcDevice, affectedSource).stream()
-                        .map(ConnectPoint::deviceId)
-                        .collect(Collectors.toSet());
-                Set<DeviceId> goodDevices = goodDevicesBySource.compute(affectedSource.deviceId(), (k, v) -> {
-                    v = v == null ? Sets.newHashSet() : v;
-                    v.addAll(localSinks);
-                    return v;
-                });
-                // TODO remove
-                log.info("Good devices {}", goodDevicesBySource);
-                Collection<? extends List<Link>> storedPathsBySource = Versioned.valueOrElse(
-                        mcastPathStore.get(mcastPathStoreKey), Lists.newArrayList());
-                Optional<? extends List<Link>> storedPath = storedPathsBySource.stream()
-                        .filter(path -> path.equals(affectedPath))
-                        .findFirst();
-                // Remove bad links
-                affectedPath.forEach(affectedLink -> {
-                    DeviceId affectedDevice = affectedLink.src().deviceId();
-                    // If there is overlap with good paths - skip it
-                    if (!goodLinks.contains(affectedLink)) {
-                        removePortFromDevice(affectedDevice, affectedLink.src().port(), mcastIp,
-                            mcastUtils.assignedVlan(affectedDevice.equals(affectedSource.deviceId()) ?
-                                                            affectedSource : null));
-                    }
-                    // Remove role on the affected links if last
-                    if (!goodDevices.contains(affectedDevice)) {
-                        mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, affectedDevice, affectedSource));
-                    }
-                });
-                // Sometimes the removal fails for serialization issue
-                // trying with the original object as workaround
-                if (storedPath.isPresent()) {
-                    mcastPathStore.remove(mcastPathStoreKey, storedPath.get());
-                } else {
-                    log.warn("Unable to find the corresponding path - trying removeal");
-                    mcastPathStore.remove(mcastPathStoreKey, affectedPath);
-                }
-                // Program new links
-                if (finalPath.isPresent()) {
-                    List<Link> links = finalPath.get().links();
-                    installPath(mcastIp, affectedSource, links);
-                    mcastPathStore.put(mcastPathStoreKey, links);
-                    links.forEach(link -> goodDevices.add(link.src().deviceId()));
-                    goodDevicesBySource.compute(srcDevice, (k, v) -> {
-                        v = v == null ? Sets.newHashSet() : v;
-                        v.addAll(goodDevices);
-                        return v;
-                    });
-                    goodLinks.addAll(finalPath.get().links());
-                }
-            });
-        });
-    }
-
-    /**
-     * Try to recover sinks using alternative locations.
-     *
-     * @param notRecovered the device not recovered
-     * @param mcastIp the group address
-     * @param affectedSources affected sources
-     * @param goodSources sources not affected
-     */
-    private Optional<Path> recoverSinks(DeviceId notRecovered, IpAddress mcastIp,
-                                    Set<ConnectPoint> affectedSources,
-                                    Set<ConnectPoint> goodSources) {
-        log.debug("Processing recover sinks on {} for group {}", notRecovered, mcastIp);
-        Map<ConnectPoint, Set<ConnectPoint>> affectedSinksBySource = Maps.newHashMap();
-        Map<ConnectPoint, Set<ConnectPoint>> sinksBySource = Maps.newHashMap();
-        Set<ConnectPoint> sources = Sets.union(affectedSources, goodSources);
-        // Hosts influenced by the failure
-        Map<HostId, Set<ConnectPoint>> hostIdSetMap = mcastUtils.getAffectedSinks(notRecovered, mcastIp);
-        // Locations influenced by the failure
-        Set<ConnectPoint> affectedSinks = hostIdSetMap.values()
-                .stream()
-                .flatMap(Collection::stream)
-                .filter(connectPoint -> connectPoint.deviceId().equals(notRecovered))
-                .collect(Collectors.toSet());
-        // All locations
-        Set<ConnectPoint> sinks = hostIdSetMap.values()
-                .stream()
-                .flatMap(Collection::stream)
-                .collect(Collectors.toSet());
-        // Maps sinks with the sources
-        sources.forEach(source -> {
-            Set<ConnectPoint> currentSinks = affectedSinks.stream()
-                    .filter(sink -> isSinkForSource(mcastIp, sink, source))
-                    .collect(Collectors.toSet());
-            affectedSinksBySource.put(source, currentSinks);
-        });
-        // Remove sinks one by one if they are not used by other sources
-        affectedSources.forEach(affectedSource -> {
-            Set<ConnectPoint> currentSinks = affectedSinksBySource.get(affectedSource);
-            log.info("Current sinks {} for source {}", currentSinks, affectedSource);
-            currentSinks.forEach(currentSink -> {
-                VlanId assignedVlan = mcastUtils.assignedVlan(
-                        affectedSource.deviceId().equals(currentSink.deviceId()) ? affectedSource : null);
-                log.info("Assigned vlan {}", assignedVlan);
-                Set<VlanId> otherVlans = goodSources.stream()
-                        .filter(remainingSource -> affectedSinksBySource.get(remainingSource).contains(currentSink))
-                        .map(remainingSource -> mcastUtils.assignedVlan(
-                                remainingSource.deviceId().equals(currentSink.deviceId()) ? remainingSource : null))
-                        .collect(Collectors.toSet());
-                log.info("Other vlans {}", otherVlans);
-                // Sinks on other leaves
-                if (!otherVlans.contains(assignedVlan)) {
-                    removePortFromDevice(currentSink.deviceId(), currentSink.port(), mcastIp, assignedVlan);
-                }
-                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(), affectedSource));
-            });
-        });
-        // Get the sinks to be added and the new egress
-        Set<DeviceId> newEgress = Sets.newHashSet();
-        affectedSources.forEach(affectedSource -> {
-            Set<ConnectPoint> currentSinks = affectedSinksBySource.get(affectedSource);
-            Set<ConnectPoint> newSinks = Sets.difference(sinks, currentSinks);
-            sinksBySource.put(affectedSource, newSinks);
-            newSinks.stream()
-                    .map(ConnectPoint::deviceId)
-                    .forEach(newEgress::add);
-        });
-        log.info("newEgress {}", newEgress);
-        // If there are more than one new egresses, return the problem
-        if (newEgress.size() != 1) {
-            log.warn("There are {} new egress, wrong configuration. Abort.", newEgress.size());
-            return Optional.empty();
-        }
-        DeviceId egress = newEgress.stream()
-                .findFirst()
-                .orElse(null);
-        DeviceId ingress = affectedSources.stream()
-                .map(ConnectPoint::deviceId)
-                .findFirst()
-                .orElse(null);
-        log.info("Ingress {}", ingress);
-        if (ingress == null) {
-            log.warn("No new ingress, wrong configuration. Abort.");
-            return Optional.empty();
-        }
-        // Get an alternative path
-        Optional<Path> alternativePath = getPath(ingress, egress, mcastIp, null);
-        // If there are new path install sinks and return path
-        if (alternativePath.isPresent()) {
-            log.info("Alternative path {}", alternativePath.get().links());
-            affectedSources.forEach(affectedSource -> {
-                Set<ConnectPoint> newSinks = sinksBySource.get(affectedSource);
-                newSinks.forEach(newSink -> {
-                    addPortToDevice(newSink.deviceId(), newSink.port(), mcastIp, mcastUtils.assignedVlan(null));
-                    mcastRoleStore.put(new McastRoleStoreKey(mcastIp, newSink.deviceId(), affectedSource), EGRESS);
-                });
-            });
-            return alternativePath;
-        }
-        // No new path but sinks co-located with sources install sinks and return empty
-        if (ingress.equals(egress)) {
-            log.info("No Alternative path but sinks co-located");
-            affectedSources.forEach(affectedSource -> {
-                Set<ConnectPoint> newSinks = sinksBySource.get(affectedSource);
-                newSinks.forEach(newSink -> {
-                    if (affectedSource.port().equals(newSink.port())) {
-                        log.warn("Skip {} since sink {} is on the same port of source {}. Abort",
-                                 mcastIp, newSink, affectedSource);
-                        return;
-                    }
-                    addPortToDevice(newSink.deviceId(), newSink.port(), mcastIp,
-                                    mcastUtils.assignedVlan(affectedSource));
-                    mcastRoleStore.put(new McastRoleStoreKey(mcastIp, newSink.deviceId(), affectedSource), INGRESS);
-                });
-            });
-        }
-        return Optional.empty();
-    }
-
-    /**
-     * Process all the sinks related to a mcast group and return
-     * the ones to be removed.
-     *
-     * @param mcastIp the group address
-     * @param prevsinks the previous sinks to be evaluated
-     * @param newSinks the new sinks to be evaluted
-     * @param source the source connect point
-     * @return the set of the sinks to be removed
-     */
-    private Set<ConnectPoint> processSinksToBeRemoved(IpAddress mcastIp,
-                                                      Map<HostId, Set<ConnectPoint>> prevsinks,
-                                                      Map<HostId, Set<ConnectPoint>> newSinks,
-                                                      ConnectPoint source) {
-        final Set<ConnectPoint> sinksToBeProcessed = Sets.newHashSet();
-        log.debug("Processing sinks to be removed for Multicast group {}, source {}",
-                  mcastIp, source);
-        prevsinks.forEach(((hostId, connectPoints) -> {
-            if (Objects.equal(HostId.NONE, hostId)) {
-                //in this case connect points are single homed sinks.
-                //just found the difference btw previous and new sinks for this source.
-                Set<ConnectPoint> difference = Sets.difference(connectPoints, newSinks.get(hostId));
-                sinksToBeProcessed.addAll(difference);
-                return;
-            }
-            // We have to check with the existing flows
-            ConnectPoint sinkToBeProcessed = connectPoints.stream()
-                    .filter(connectPoint -> isSinkForSource(mcastIp, connectPoint, source))
-                    .findFirst().orElse(null);
-            if (sinkToBeProcessed != null) {
-                // If the host has been removed or location has been removed
-                if (!newSinks.containsKey(hostId) ||
-                        !newSinks.get(hostId).contains(sinkToBeProcessed)) {
-                    sinksToBeProcessed.add(sinkToBeProcessed);
-                }
-            }
-        }));
-        // We have done, return the set
-        return sinksToBeProcessed;
-    }
-
-    /**
-     * Process new locations and return the set of sinks to be added
-     * in the context of the recovery.
-     *
-     * @param newSinks the remaining sinks
-     * @param prevSinks the previous sinks
-     * @param source the source connect point
-     * @return the set of the sinks to be processed
-     */
-    private Set<ConnectPoint> processSinksToBeRecovered(IpAddress mcastIp,
-                                                        Map<HostId, Set<ConnectPoint>> newSinks,
-                                                        Map<HostId, Set<ConnectPoint>> prevSinks,
-                                                        ConnectPoint source) {
-        final Set<ConnectPoint> sinksToBeProcessed = Sets.newHashSet();
-        log.debug("Processing sinks to be recovered for Multicast group {}, source {}",
-                  mcastIp, source);
-        newSinks.forEach((hostId, connectPoints) -> {
-            // If it has more than 1 locations
-            if (connectPoints.size() > 1 || connectPoints.size() == 0) {
-                log.debug("Skip {} since sink {} has {} locations",
-                         mcastIp, hostId, connectPoints.size());
-                return;
-            }
-            // If previously it had two locations, we need to recover it
-            // Filter out if the remaining location is already served
-            if (prevSinks.containsKey(hostId) && prevSinks.get(hostId).size() == 2) {
-                ConnectPoint sinkToBeProcessed = connectPoints.stream()
-                        .filter(connectPoint -> !isSinkForSource(mcastIp, connectPoint, source))
-                        .findFirst().orElse(null);
-                if (sinkToBeProcessed != null) {
-                    sinksToBeProcessed.add(sinkToBeProcessed);
-                }
-            }
-        });
-        return sinksToBeProcessed;
-    }
-
-    /**
-     * Process all the sinks related to a mcast group and return
-     * the ones to be processed.
-     *
-     * @param source the source connect point
-     * @param mcastIp the group address
-     * @param sinks the sinks to be evaluated
-     * @return the set of the sinks to be processed
-     */
-    private Set<ConnectPoint> processSinksToBeAdded(ConnectPoint source, IpAddress mcastIp,
-                                                    Map<HostId, Set<ConnectPoint>> sinks) {
-        final Set<ConnectPoint> sinksToBeProcessed = Sets.newHashSet();
-        log.debug("Processing sinks to be added for Multicast group {}, source {}",
-                  mcastIp, source);
-        sinks.forEach(((hostId, connectPoints) -> {
-            //add all connect points that are not tied with any host
-            if (Objects.equal(HostId.NONE, hostId)) {
-                sinksToBeProcessed.addAll(connectPoints);
-                return;
-            }
-            // If it has more than 2 locations
-            if (connectPoints.size() > 2 || connectPoints.size() == 0) {
-                log.debug("Skip {} since sink {} has {} locations",
-                         mcastIp, hostId, connectPoints.size());
-                return;
-            }
-            // If it has one location, just use it
-            if (connectPoints.size() == 1) {
-                sinksToBeProcessed.add(connectPoints.stream().findFirst().orElse(null));
-                return;
-            }
-            // We prefer to reuse existing flows
-            ConnectPoint sinkToBeProcessed = connectPoints.stream()
-                    .filter(connectPoint -> {
-                        if (!isSinkForGroup(mcastIp, connectPoint, source)) {
-                            return false;
-                        }
-                        if (!isSinkReachable(mcastIp, connectPoint, source)) {
-                            return false;
-                        }
-                        ConnectPoint other = connectPoints.stream()
-                                .filter(remaining -> !remaining.equals(connectPoint))
-                                .findFirst().orElse(null);
-                        // We are already serving the sink
-                        return !isSinkForSource(mcastIp, other, source);
-                    }).findFirst().orElse(null);
-
-            if (sinkToBeProcessed != null) {
-                sinksToBeProcessed.add(sinkToBeProcessed);
-                return;
-            }
-            // Otherwise we prefer to reuse existing egresses
-            Set<DeviceId> egresses = getDevice(mcastIp, EGRESS, source);
-            sinkToBeProcessed = connectPoints.stream()
-                    .filter(connectPoint -> {
-                        if (!egresses.contains(connectPoint.deviceId())) {
-                            return false;
-                        }
-                        if (!isSinkReachable(mcastIp, connectPoint, source)) {
-                            return false;
-                        }
-                        ConnectPoint other = connectPoints.stream()
-                                .filter(remaining -> !remaining.equals(connectPoint))
-                                .findFirst().orElse(null);
-                        return !isSinkForSource(mcastIp, other, source);
-                    }).findFirst().orElse(null);
-            if (sinkToBeProcessed != null) {
-                sinksToBeProcessed.add(sinkToBeProcessed);
-                return;
-            }
-            // Otherwise we prefer a location co-located with the source (if it exists)
-            sinkToBeProcessed = connectPoints.stream()
-                    .filter(connectPoint -> connectPoint.deviceId().equals(source.deviceId()))
-                    .findFirst().orElse(null);
-            if (sinkToBeProcessed != null) {
-                sinksToBeProcessed.add(sinkToBeProcessed);
-                return;
-            }
-            // Finally, we randomly pick a new location if it is reachable
-            sinkToBeProcessed = connectPoints.stream()
-                    .filter(connectPoint -> {
-                        if (!isSinkReachable(mcastIp, connectPoint, source)) {
-                            return false;
-                        }
-                        ConnectPoint other = connectPoints.stream()
-                                .filter(remaining -> !remaining.equals(connectPoint))
-                                .findFirst().orElse(null);
-                        return !isSinkForSource(mcastIp, other, source);
-                    }).findFirst().orElse(null);
-            if (sinkToBeProcessed != null) {
-                sinksToBeProcessed.add(sinkToBeProcessed);
-            }
-        }));
-        return sinksToBeProcessed;
-    }
-
-    /**
-     * Adds a port to given multicast group on given device. This involves the
-     * update of L3 multicast group and multicast routing table entry.
-     *
-     * @param deviceId device ID
-     * @param port port to be added
-     * @param mcastIp multicast group
-     * @param assignedVlan assigned VLAN ID
-     */
-    private void addPortToDevice(DeviceId deviceId, PortNumber port,
-                                 IpAddress mcastIp, VlanId assignedVlan) {
-        // TODO trace
-        log.info("Adding {} on {}/{} and vlan {}", mcastIp, deviceId, port, assignedVlan);
-        McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
-        ImmutableSet.Builder<PortNumber> portBuilder = ImmutableSet.builder();
-        NextObjective newNextObj;
-        if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
-            // First time someone request this mcast group via this device
-            portBuilder.add(port);
-            // New nextObj
-            if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-                log.debug("Passing 0 as nextId for unconfigured device {}", deviceId);
-                newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
-                                            portBuilder.build(), 0).add();
-            } else {
-                newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
-                                            portBuilder.build(), null).add();
-            }
-            // Store the new port
-            mcastNextObjStore.put(mcastStoreKey, newNextObj);
-            // Create, store and apply the new nextObj and fwdObj
-            ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Successfully add {} on {}/{}, vlan {}",
-                        mcastIp, deviceId, port.toLong(), assignedVlan),
-                (objective, error) -> {
-                    log.warn("Failed to add {} on {}/{}, vlan {}: {}",
-                            mcastIp, deviceId, port.toLong(), assignedVlan, error);
-                    // Schedule the removal using directly the key
-                    mcastWorker.execute(() -> mcastNextObjStore.remove(mcastStoreKey));
-                });
-            ForwardingObjective fwdObj = mcastUtils.fwdObjBuilder(mcastIp, assignedVlan,
-                                                          newNextObj.id()).add(context);
-            if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-                log.debug("skip next and forward flowobjective addition for device: {}", deviceId);
-            } else {
-                srManager.flowObjectiveService.next(deviceId, newNextObj);
-                srManager.flowObjectiveService.forward(deviceId, fwdObj);
-            }
-        } else {
-            // This device already serves some subscribers of this mcast group
-            NextObjective nextObj = mcastNextObjStore.get(mcastStoreKey).value();
-            // Stop if the port is already in the nextobj
-            Set<PortNumber> existingPorts = mcastUtils.getPorts(nextObj.next());
-            if (existingPorts.contains(port)) {
-                log.debug("Port {}/{} already exists for {}. Abort", deviceId, port, mcastIp);
-                return;
-            }
-            // Let's add the port and reuse the previous one
-            portBuilder.addAll(existingPorts).add(port);
-            // Reuse previous nextObj
-            newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
-                                        portBuilder.build(), nextObj.id()).addToExisting();
-            // Store the final next objective and send only the difference to the driver
-            mcastNextObjStore.put(mcastStoreKey, newNextObj);
-            // Add just the new port
-            portBuilder = ImmutableSet.builder();
-            portBuilder.add(port);
-            newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
-                                        portBuilder.build(), nextObj.id()).addToExisting();
-            if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-                log.debug("skip next flowobjective update for device: {}", deviceId);
-            } else {
-                // no need to update the flow here since we have updated the nextobjective/group
-                // the existing flow will keep pointing to the updated nextobj
-                srManager.flowObjectiveService.next(deviceId, newNextObj);
-            }
-        }
-    }
-
-    /**
-     * Removes a port from given multicast group on given device.
-     * This involves the update of L3 multicast group and multicast routing
-     * table entry.
-     *
-     * @param deviceId device ID
-     * @param port port to be added
-     * @param mcastIp multicast group
-     * @param assignedVlan assigned VLAN ID
-     * @return true if this is the last sink on this device
-     */
-    private boolean removePortFromDevice(DeviceId deviceId, PortNumber port,
-                                         IpAddress mcastIp, VlanId assignedVlan) {
-        // TODO trace
-        log.info("Removing {} on {}/{} and vlan {}", mcastIp, deviceId, port, assignedVlan);
-        McastStoreKey mcastStoreKey =
-                new McastStoreKey(mcastIp, deviceId, assignedVlan);
-        // This device is not serving this multicast group
-        if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
-            return true;
-        }
-        NextObjective nextObj = mcastNextObjStore.get(mcastStoreKey).value();
-        Set<PortNumber> existingPorts = mcastUtils.getPorts(nextObj.next());
-        // This port does not serve this multicast group
-        if (!existingPorts.contains(port)) {
-            if (!existingPorts.isEmpty()) {
-                log.debug("{} is not serving {} on port {}. Abort.", deviceId, mcastIp, port);
-                return false;
-            }
-            return true;
-        }
-        // Copy and modify the ImmutableSet
-        existingPorts = Sets.newHashSet(existingPorts);
-        existingPorts.remove(port);
-        NextObjective newNextObj;
-        ObjectiveContext context;
-        ForwardingObjective fwdObj;
-        if (existingPorts.isEmpty()) {
-            context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("Successfully remove {} on {}/{}, vlan {}",
-                            mcastIp, deviceId, port.toLong(), assignedVlan),
-                    (objective, error) -> log.warn("Failed to remove {} on {}/{}, vlan {}: {}",
-                                    mcastIp, deviceId, port.toLong(), assignedVlan, error));
-            fwdObj = mcastUtils.fwdObjBuilder(mcastIp, assignedVlan, nextObj.id()).remove(context);
-            if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-                log.debug("skip forward flowobjective removal for device: {}", deviceId);
-            } else {
-                srManager.flowObjectiveService.forward(deviceId, fwdObj);
-            }
-            mcastNextObjStore.remove(mcastStoreKey);
-        } else {
-            // Here we store the next objective with the remaining port
-            newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
-                                        existingPorts, nextObj.id()).removeFromExisting();
-            mcastNextObjStore.put(mcastStoreKey, newNextObj);
-             // Let's modify the next objective removing the bucket
-            newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
-                                    ImmutableSet.of(port), nextObj.id()).removeFromExisting();
-            if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-                log.debug("skip next flowobjective update for device: {}", deviceId);
-            } else {
-                // no need to update the flow here since we have updated the next objective + group
-                // the existing flow will keep pointing to the updated nextobj
-                srManager.flowObjectiveService.next(deviceId, newNextObj);
-            }
-        }
-        return existingPorts.isEmpty();
-    }
-
-    /**
-     * Removes entire group on given device.
-     *
-     * @param deviceId device ID
-     * @param mcastIp multicast group to be removed
-     * @param assignedVlan assigned VLAN ID
-     */
-    private void removeGroupFromDevice(DeviceId deviceId, IpAddress mcastIp,
-                                       VlanId assignedVlan) {
-        // TODO trace
-        log.info("Removing {} on {} and vlan {}", mcastIp, deviceId, assignedVlan);
-        McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
-        // This device is not serving this multicast group
-        if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
-            log.debug("{} is not serving {}. Abort.", deviceId, mcastIp);
-            return;
-        }
-        NextObjective nextObj = mcastNextObjStore.get(mcastStoreKey).value();
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Successfully remove {} on {}, vlan {}",
-                        mcastIp, deviceId, assignedVlan),
-                (objective, error) -> log.warn("Failed to remove {} on {}, vlan {}: {}",
-                                mcastIp, deviceId, assignedVlan, error));
-        if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-            log.debug("skip flow changes on unconfigured device: {}", deviceId);
-        } else {
-            ForwardingObjective fwdObj = mcastUtils.fwdObjBuilder(mcastIp, assignedVlan, nextObj.id()).remove(context);
-            srManager.flowObjectiveService.forward(deviceId, fwdObj);
-        }
-        mcastNextObjStore.remove(mcastStoreKey);
-    }
-
-    private void installPath(IpAddress mcastIp, ConnectPoint source, List<Link> links) {
-        if (links.isEmpty()) {
-            log.warn("There is no link that can be used. Stopping installation.");
-            return;
-        }
-        // Setup new ingress mcast role
-        mcastRoleStore.put(new McastRoleStoreKey(mcastIp, links.get(0).src().deviceId(), source),
-                           INGRESS);
-        // For each link, modify the next on the source device adding the src port
-        // and a new filter objective on the destination port
-        links.forEach(link -> {
-            addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp,
-                mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
-            McastFilteringObjStoreKey mcastFilterObjStoreKey = new McastFilteringObjStoreKey(link.dst(),
-                    mcastUtils.assignedVlan(null), mcastIp.isIp4());
-            addFilterToDevice(mcastFilterObjStoreKey, mcastIp, null);
-        });
-        // Setup mcast role for the transit
-        links.stream()
-                .filter(link -> !link.src().deviceId().equals(source.deviceId()))
-                .forEach(link -> mcastRoleStore.put(new McastRoleStoreKey(mcastIp, link.src().deviceId(), source),
-                                                    TRANSIT));
-    }
-
-    /**
-     * Gets a path from src to dst.
-     * If a path was allocated before, returns the allocated path.
-     * Otherwise, randomly pick one from available paths.
-     *
-     * @param src source device ID
-     * @param dst destination device ID
-     * @param mcastIp multicast group
-     * @param allPaths paths list
-     *
-     * @return an optional path from src to dst
-     */
-    private Optional<Path> getPath(DeviceId src, DeviceId dst,
-                                   IpAddress mcastIp, List<Path> allPaths) {
-        if (allPaths == null) {
-            allPaths = mcastUtils.getPaths(src, dst, Collections.emptySet());
-        }
-        if (allPaths.isEmpty()) {
-            return Optional.empty();
-        }
-        // Create a map index of suitability-to-list of paths. For example
-        // a path in the list associated to the index 1 shares only one link
-        // and it is less suitable of a path belonging to the index 2
-        Map<Integer, List<Path>> eligiblePaths = Maps.newHashMap();
-        int score;
-        // Let's build the multicast tree
-        Set<List<Link>> storedPaths = getStoredPaths(mcastIp);
-        Set<Link> storedTree = storedPaths.stream()
-                .flatMap(Collection::stream).collect(Collectors.toSet());
-        log.trace("Stored tree {}", storedTree);
-        Set<Link> pathLinks;
-        for (Path path : allPaths) {
-            if (!src.equals(path.links().get(0).src().deviceId())) {
-                continue;
-            }
-            pathLinks = Sets.newHashSet(path.links());
-            score = Sets.intersection(pathLinks, storedTree).size();
-            // score defines the index
-            if (score > 0) {
-                eligiblePaths.compute(score, (index, paths) -> {
-                    paths = paths == null ? Lists.newArrayList() : paths;
-                    paths.add(path);
-                    return paths;
-                });
-            }
-        }
-        if (eligiblePaths.isEmpty()) {
-            log.trace("No eligiblePath(s) found from {} to {}", src, dst);
-            Collections.shuffle(allPaths);
-            return allPaths.stream().findFirst();
-        }
-        // Let's take the best ones
-        Integer bestIndex = eligiblePaths.keySet().stream()
-                .sorted(Comparator.reverseOrder()).findFirst().orElse(null);
-        List<Path> bestPaths = eligiblePaths.get(bestIndex);
-        log.trace("{} eligiblePath(s) found from {} to {}",
-                  bestPaths.size(), src, dst);
-        Collections.shuffle(bestPaths);
-        return bestPaths.stream().findFirst();
-    }
-
-    /**
-     * Gets stored paths of the group.
-     *
-     * @param mcastIp group address
-     * @return a collection of paths
-     */
-    private Set<List<Link>> getStoredPaths(IpAddress mcastIp) {
-        return mcastPathStore.stream()
-                .filter(entry -> entry.getKey().mcastIp().equals(mcastIp))
-                .map(Entry::getValue)
-                .collect(Collectors.toSet());
-    }
-
-    /**
-     * Gets device(s) of given role and of given source in given multicast tree.
-     *
-     * @param mcastIp multicast IP
-     * @param role multicast role
-     * @param source source connect point
-     * @return set of device ID or empty set if not found
-     */
-    private Set<DeviceId> getDevice(IpAddress mcastIp, McastRole role, ConnectPoint source) {
-        return mcastRoleStore.entrySet().stream()
-                .filter(entry -> entry.getKey().mcastIp().equals(mcastIp) &&
-                        entry.getKey().source().equals(source) &&
-                        entry.getValue().value() == role)
-                .map(Entry::getKey).map(McastRoleStoreKey::deviceId).collect(Collectors.toSet());
-    }
-
-    /**
-     * Gets device(s) of given role in given multicast group.
-     *
-     * @param mcastIp multicast IP
-     * @param role multicast role
-     * @return set of device ID or empty set if not found
-     */
-    private Set<DeviceId> getDevice(IpAddress mcastIp, McastRole role) {
-        return mcastRoleStore.entrySet().stream()
-                .filter(entry -> entry.getKey().mcastIp().equals(mcastIp) &&
-                        entry.getValue().value() == role)
-                .map(Entry::getKey).map(McastRoleStoreKey::deviceId).collect(Collectors.toSet());
-    }
-
-    /**
-     * Gets source(s) of given multicast group.
-     *
-     * @param mcastIp multicast IP
-     * @return set of device ID or empty set if not found
-     */
-    private Set<ConnectPoint> getSources(IpAddress mcastIp) {
-        return mcastRoleStore.entrySet().stream()
-                .filter(entry -> entry.getKey().mcastIp().equals(mcastIp))
-                .map(Entry::getKey).map(McastRoleStoreKey::source).collect(Collectors.toSet());
-    }
-
-    /**
-     * Gets sink(s) of given multicast group.
-     *
-     * @param mcastIp multicast IP
-     * @return set of connect point or empty set if not found
-     */
-    private Set<ConnectPoint> getSinks(IpAddress mcastIp, DeviceId device, ConnectPoint source) {
-        McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-        Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
-                mcastPathStore.get(pathStoreKey), Lists.newArrayList());
-        VlanId assignedVlan = mcastUtils.assignedVlan(device.equals(source.deviceId()) ? source : null);
-        McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, device, assignedVlan);
-        NextObjective nextObjective = Versioned.valueOrNull(mcastNextObjStore.get(mcastStoreKey));
-        ImmutableSet.Builder<ConnectPoint> cpBuilder = ImmutableSet.builder();
-        if (nextObjective != null) {
-            Set<PortNumber> outputPorts = mcastUtils.getPorts(nextObjective.next());
-            outputPorts.forEach(portNumber -> cpBuilder.add(new ConnectPoint(device, portNumber)));
-        }
-        Set<ConnectPoint> egressCp = cpBuilder.build();
-        return egressCp.stream()
-                .filter(connectPoint -> !mcastUtils.isInfraPort(connectPoint, storedPaths))
-                .collect(Collectors.toSet());
-    }
-
-
-
-    /**
-     * Gets groups which is affected by the link down event.
-     *
-     * @param link link going down
-     * @return a set of multicast IpAddress
-     */
-    private Set<IpAddress> getAffectedGroups(Link link) {
-        DeviceId deviceId = link.src().deviceId();
-        PortNumber port = link.src().port();
-        return mcastNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(deviceId) &&
-                    mcastUtils.getPorts(entry.getValue().value().next()).contains(port))
-                .map(Entry::getKey).map(McastStoreKey::mcastIp).collect(Collectors.toSet());
-    }
-
-    /**
-     * Gets groups which are affected by the device down event.
-     *
-     * @param deviceId device going down
-     * @return a set of multicast IpAddress
-     */
-    private Set<IpAddress> getAffectedGroups(DeviceId deviceId) {
-        return mcastNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(deviceId))
-                .map(Entry::getKey).map(McastStoreKey::mcastIp)
-                .collect(Collectors.toSet());
-    }
-
-    /**
-     * Verify if a given connect point is sink for this group.
-     *
-     * @param mcastIp group address
-     * @param connectPoint connect point to be verified
-     * @param source source connect point
-     * @return true if the connect point is sink of the group
-     */
-    private boolean isSinkForGroup(IpAddress mcastIp, ConnectPoint connectPoint,
-                                   ConnectPoint source) {
-        VlanId assignedVlan = mcastUtils.assignedVlan(connectPoint.deviceId().equals(source.deviceId()) ?
-                                                              source : null);
-        McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, connectPoint.deviceId(), assignedVlan);
-        if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
-            return false;
-        }
-        NextObjective mcastNext = mcastNextObjStore.get(mcastStoreKey).value();
-        return mcastUtils.getPorts(mcastNext.next()).contains(connectPoint.port());
-    }
-
-    /**
-     * Verify if a given connect point is sink for this group and for this source.
-     *
-     * @param mcastIp group address
-     * @param connectPoint connect point to be verified
-     * @param source source connect point
-     * @return true if the connect point is sink of the group
-     */
-    private boolean isSinkForSource(IpAddress mcastIp, ConnectPoint connectPoint,
-                                    ConnectPoint source) {
-        boolean isSink = isSinkForGroup(mcastIp, connectPoint, source);
-        DeviceId device;
-        if (connectPoint.deviceId().equals(source.deviceId())) {
-            device = getDevice(mcastIp, INGRESS, source).stream()
-                    .filter(deviceId -> deviceId.equals(connectPoint.deviceId()))
-                    .findFirst().orElse(null);
-        } else {
-            device = getDevice(mcastIp, EGRESS, source).stream()
-                    .filter(deviceId -> deviceId.equals(connectPoint.deviceId()))
-                    .findFirst().orElse(null);
-        }
-        return isSink && device != null;
-    }
-
-    /**
-     * Verify if a sink is reachable from this source.
-     *
-     * @param mcastIp group address
-     * @param sink connect point to be verified
-     * @param source source connect point
-     * @return true if the connect point is reachable from the source
-     */
-    private boolean isSinkReachable(IpAddress mcastIp, ConnectPoint sink,
-                                    ConnectPoint source) {
-        return sink.deviceId().equals(source.deviceId()) ||
-                getPath(source.deviceId(), sink.deviceId(), mcastIp, null).isPresent();
-    }
-
-    /**
-     * Updates filtering objective for given device and port.
-     * It is called in general when the mcast config has been
-     * changed.
-     *
-     * @param deviceId device ID
-     * @param portNum ingress port number
-     * @param vlanId assigned VLAN ID
-     * @param install true to add, false to remove
-     */
-    public void updateFilterToDevice(DeviceId deviceId, PortNumber portNum,
-                                        VlanId vlanId, boolean install) {
-        mcastWorker.execute(() -> updateFilterToDeviceInternal(deviceId, portNum, vlanId, install));
-    }
-
-    private void updateFilterToDeviceInternal(DeviceId deviceId, PortNumber portNum,
-                                              VlanId vlanId, boolean install) {
-        lastMcastChange.set(Instant.now());
-        // Iterates over the route and updates properly the filtering objective on the source device.
-        srManager.multicastRouteService.getRoutes().forEach(mcastRoute -> {
-            log.debug("Update filter for {}", mcastRoute.group());
-            if (!mcastUtils.isLeader(mcastRoute.group())) {
-                log.debug("Skip {} due to lack of leadership", mcastRoute.group());
-                return;
-            }
-            // Get the sources and for each one update properly the filtering objectives
-            Set<ConnectPoint> sources = srManager.multicastRouteService.sources(mcastRoute);
-            sources.forEach(source -> {
-                if (source.deviceId().equals(deviceId) && source.port().equals(portNum)) {
-                    if (install) {
-                        McastFilteringObjStoreKey mcastFilterObjStoreKey = new McastFilteringObjStoreKey(source,
-                                                                             vlanId, mcastRoute.group().isIp4());
-                        addFilterToDevice(mcastFilterObjStoreKey, mcastRoute.group(), INGRESS);
-                    } else {
-                        mcastUtils.removeFilterToDevice(deviceId, portNum, vlanId, mcastRoute.group(), null);
-                    }
-                }
-            });
-        });
-    }
-
-    /**
-     * Add filtering to the device if needed.
-     *
-     * @param filterObjStoreKey the filtering obj key
-     * @param mcastIp the multicast group
-     * @param mcastRole the multicast role
-     */
-    private void addFilterToDevice(McastFilteringObjStoreKey filterObjStoreKey,
-                                   IpAddress mcastIp,
-                                   McastRole mcastRole) {
-        if (!containsFilterInTheDevice(filterObjStoreKey)) {
-            // if this is the first sink for this group/device
-            // match additionally on mac
-            log.debug("Filtering not available for device {}, vlan {} and {}",
-                      filterObjStoreKey.ingressCP().deviceId(), filterObjStoreKey.vlanId(),
-                      filterObjStoreKey.isIpv4() ? "IPv4" : "IPv6");
-            mcastUtils.addFilterToDevice(filterObjStoreKey.ingressCP().deviceId(),
-                                         filterObjStoreKey.ingressCP().port(),
-                                         filterObjStoreKey.vlanId(), mcastIp,
-                                         mcastRole, true);
-            mcastFilteringObjStore.add(filterObjStoreKey);
-        } else if (!mcastFilteringObjStore.contains(filterObjStoreKey)) {
-            // match only vlan
-            log.debug("Filtering not available for connect point {}, vlan {} and {}",
-                      filterObjStoreKey.ingressCP(), filterObjStoreKey.vlanId(),
-                      filterObjStoreKey.isIpv4() ? "IPv4" : "IPv6");
-            mcastUtils.addFilterToDevice(filterObjStoreKey.ingressCP().deviceId(),
-                                         filterObjStoreKey.ingressCP().port(),
-                                         filterObjStoreKey.vlanId(), mcastIp,
-                                         mcastRole, false);
-            mcastFilteringObjStore.add(filterObjStoreKey);
-        } else {
-            // do nothing
-            log.debug("Filtering already present for connect point {}, vlan {} and {}. Abort",
-                      filterObjStoreKey.ingressCP(), filterObjStoreKey.vlanId(),
-                      filterObjStoreKey.isIpv4() ? "IPv4" : "IPv6");
-        }
-    }
-
-    /**
-     * Verify if there are related filtering obj in the device.
-     *
-     * @param filteringKey the filtering obj key
-     * @return true if related filtering obj are found
-     */
-    private boolean containsFilterInTheDevice(McastFilteringObjStoreKey filteringKey) {
-        // check if filters are already added on the device
-        McastFilteringObjStoreKey key = mcastFilteringObjStore.stream()
-                .filter(mcastFilteringKey ->
-                                mcastFilteringKey.ingressCP().deviceId().equals(filteringKey.ingressCP().deviceId())
-                                        && mcastFilteringKey.isIpv4() == filteringKey.isIpv4()
-                                        && mcastFilteringKey.vlanId().equals(filteringKey.vlanId())
-                ).findFirst().orElse(null);
-        // we are interested to filt obj on the same device, same vlan and same ip type
-        return key != null;
-    }
-
-    /**
-     * Update the filtering objective store upon device failure.
-     *
-     * @param affectedDevice the affected device
-     */
-    private void updateFilterObjStoreByDevice(DeviceId affectedDevice) {
-        // purge the related filter objective key
-        Set<McastFilteringObjStoreKey> filterObjs = Sets.newHashSet(mcastFilteringObjStore);
-        Iterator<McastFilteringObjStoreKey> filterIterator = filterObjs.iterator();
-        McastFilteringObjStoreKey filterKey;
-        while (filterIterator.hasNext()) {
-            filterKey = filterIterator.next();
-            if (filterKey.ingressCP().deviceId().equals(affectedDevice)) {
-                mcastFilteringObjStore.remove(filterKey);
-            }
-        }
-    }
-
-    /**
-     * Update the filtering objective store upon port failure.
-     *
-     * @param affectedPort the affected port
-     */
-    private void updateFilterObjStoreByPort(ConnectPoint affectedPort) {
-        // purge the related filter objective key
-        Set<McastFilteringObjStoreKey> filterObjs = Sets.newHashSet(mcastFilteringObjStore);
-        Iterator<McastFilteringObjStoreKey> filterIterator = filterObjs.iterator();
-        McastFilteringObjStoreKey filterKey;
-        while (filterIterator.hasNext()) {
-            filterKey = filterIterator.next();
-            if (filterKey.ingressCP().equals(affectedPort)) {
-                mcastFilteringObjStore.remove(filterKey);
-            }
-        }
-    }
-
-    /**
-     * Performs bucket verification operation for all mcast groups in the devices.
-     * Firstly, it verifies that mcast is stable before trying verification operation.
-     * Verification consists in creating new nexts with VERIFY operation. Actually,
-     * the operation is totally delegated to the driver.
-     */
-    private final class McastBucketCorrector implements Runnable {
-        private final AtomicInteger verifyOnFlight = new AtomicInteger(0);
-        // Define the context used for the back pressure mechanism
-        private final ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> {
-                    synchronized (verifyOnFlight) {
-                        log.trace("Verify {} done", objective.id());
-                        verifyOnFlight.updateAndGet(i -> i > 0 ? i - 1 : i);
-                        verifyOnFlight.notify();
-                    }
-                },
-                (objective, error) -> {
-                    synchronized (verifyOnFlight) {
-                        log.trace("Verify {} error {}", objective.id(), error);
-                        verifyOnFlight.updateAndGet(i -> i > 0 ? i - 1 : i);
-                        verifyOnFlight.notify();
-                    }
-                });
-
-        @Override
-        public void run() {
-            try {
-                // Iterates over the routes and verify the related next objectives
-                for (McastRoute mcastRoute : srManager.multicastRouteService.getRoutes()) {
-                    if (!isMcastStable() || wasBktCorrRunning()) {
-                        return;
-                    }
-                    IpAddress mcastIp = mcastRoute.group();
-                    log.trace("Running mcast buckets corrector for mcast group: {}", mcastIp);
-                    // Verify leadership on the operation
-                    if (!mcastUtils.isLeader(mcastIp)) {
-                        log.trace("Skip {} due to lack of leadership", mcastIp);
-                        continue;
-                    }
-                    // Get sources and sinks from Mcast Route Service and warn about errors
-                    Set<ConnectPoint> sources = mcastUtils.getSources(mcastIp);
-                    Set<ConnectPoint> sinks = mcastUtils.getSinks(mcastIp).values().stream()
-                            .flatMap(Collection::stream).collect(Collectors.toSet());
-                    // Do not proceed if sources of this group are missing
-                    if (sources.isEmpty()) {
-                        if (!sinks.isEmpty()) {
-                            log.warn("Unable to run buckets corrector. " +
-                                     "Missing source {} for group {}", sources, mcastIp);
-                        }
-                        continue;
-                    }
-                    // For each group we get current information in the store
-                    // and issue a check of the next objectives in place
-                    Set<McastStoreKey> processedKeys = Sets.newHashSet();
-                    for (ConnectPoint source : sources) {
-                        Set<DeviceId> ingressDevices = getDevice(mcastIp, INGRESS, source);
-                        Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT, source);
-                        Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS, source);
-                        // Do not proceed if ingress devices are missing
-                        if (ingressDevices.isEmpty()) {
-                            if (!sinks.isEmpty()) {
-                                log.warn("Unable to run buckets corrector. " +
-                                "Missing ingress {} for source {} and for group {}",
-                                         ingressDevices, source, mcastIp);
-                            }
-                            continue;
-                        }
-                        // Create the set of the devices to be processed
-                        ImmutableSet.Builder<DeviceId> devicesBuilder = ImmutableSet.builder();
-                        devicesBuilder.addAll(ingressDevices);
-                        if (!transitDevices.isEmpty()) {
-                            devicesBuilder.addAll(transitDevices);
-                        }
-                        if (!egressDevices.isEmpty()) {
-                            devicesBuilder.addAll(egressDevices);
-                        }
-                        Set<DeviceId> devicesToProcess = devicesBuilder.build();
-                        for (DeviceId deviceId : devicesToProcess) {
-                            if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-                                log.trace("Skipping Bucket corrector for unconfigured device {}", deviceId);
-                                continue;
-                            }
-                            synchronized (verifyOnFlight) {
-                                while (verifyOnFlight.get() == MAX_VERIFY_ON_FLIGHT) {
-                                    verifyOnFlight.wait();
-                                }
-                            }
-                            VlanId assignedVlan = mcastUtils.assignedVlan(deviceId.equals(source.deviceId()) ?
-                                                                                  source : null);
-                            McastStoreKey currentKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
-                            // Check if we already processed this next - trees merge at some point
-                            if (processedKeys.contains(currentKey)) {
-                                continue;
-                            }
-                            // Verify the nextobjective or skip to next device
-                            if (mcastNextObjStore.containsKey(currentKey)) {
-                                NextObjective currentNext = mcastNextObjStore.get(currentKey).value();
-                                // Rebuild the next objective using assigned vlan
-                                currentNext = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
-                                            mcastUtils.getPorts(currentNext.next()), currentNext.id()).verify(context);
-                                // Send to the flowobjective service
-                                srManager.flowObjectiveService.next(deviceId, currentNext);
-                                verifyOnFlight.incrementAndGet();
-                                log.trace("Verify on flight {}", verifyOnFlight);
-                                processedKeys.add(currentKey);
-                            } else {
-                                log.warn("Unable to run buckets corrector. " +
-                                         "Missing next for {}, for source {} and for group {}",
-                                         deviceId, source, mcastIp);
-                            }
-                        }
-                    }
-                    // Let's wait the group before start the next one
-                    synchronized (verifyOnFlight) {
-                        while (verifyOnFlight.get() > 0) {
-                            verifyOnFlight.wait();
-                        }
-                    }
-                }
-            } catch (InterruptedException e) {
-                log.warn("BktCorr has been interrupted");
-            } finally {
-                lastBktCorrExecution.set(Instant.now());
-            }
-        }
-    }
-
-    /**
-     * Returns the associated next ids to the mcast groups or to the single
-     * group if mcastIp is present.
-     *
-     * @param mcastIp the group ip
-     * @return the mapping mcastIp-device to next id
-     */
-    public Map<McastStoreKey, Integer> getNextIds(IpAddress mcastIp) {
-        log.info("mcastNexts {}", mcastNextObjStore.size());
-        if (mcastIp != null) {
-            return mcastNextObjStore.entrySet().stream()
-                    .filter(mcastEntry -> mcastIp.equals(mcastEntry.getKey().mcastIp()))
-                    .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().value().id()));
-        }
-        return mcastNextObjStore.entrySet().stream()
-                .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().value().id()));
-    }
-
-    /**
-     * Removes given next ID from mcast next id store.
-     *
-     * @param nextId next id
-     */
-    public void removeNextId(int nextId) {
-        mcastNextObjStore.entrySet().forEach(e -> {
-            if (e.getValue().value().id() == nextId) {
-                mcastNextObjStore.remove(e.getKey());
-            }
-        });
-    }
-
-    /**
-     * Build the mcast paths.
-     *
-     * @param storedPaths mcast tree
-     * @param mcastIp the group ip
-     * @param source the source
-     */
-    private Map<ConnectPoint, List<ConnectPoint>> buildMcastPaths(Collection<? extends List<Link>> storedPaths,
-                                                                  IpAddress mcastIp, ConnectPoint source) {
-        Map<ConnectPoint, List<ConnectPoint>> mcastTree = Maps.newHashMap();
-        // Local sinks
-        Set<ConnectPoint> localSinks = getSinks(mcastIp, source.deviceId(), source);
-        localSinks.forEach(localSink -> mcastTree.put(localSink, Lists.newArrayList(localSink, source)));
-        // Remote sinks
-        storedPaths.forEach(path -> {
-            List<Link> links = path;
-            DeviceId egressDevice = links.get(links.size() - 1).dst().deviceId();
-            Set<ConnectPoint> remoteSinks = getSinks(mcastIp, egressDevice, source);
-            List<ConnectPoint> connectPoints = Lists.newArrayList(source);
-            links.forEach(link -> {
-                connectPoints.add(link.src());
-                connectPoints.add(link.dst());
-            });
-            Collections.reverse(connectPoints);
-            remoteSinks.forEach(remoteSink -> {
-                List<ConnectPoint> finalPath = Lists.newArrayList(connectPoints);
-                finalPath.add(0, remoteSink);
-                mcastTree.put(remoteSink, finalPath);
-            });
-        });
-        return mcastTree;
-    }
-
-    /**
-     * Returns the associated roles to the mcast groups.
-     *
-     * @param mcastIp the group ip
-     * @param sourcecp the source connect point
-     * @return the mapping mcastIp-device to mcast role
-     */
-    public Map<McastRoleStoreKey, McastRole> getMcastRoles(IpAddress mcastIp,
-                                                       ConnectPoint sourcecp) {
-        log.info("mcastRoles {}", mcastRoleStore.size());
-        if (mcastIp != null) {
-            Map<McastRoleStoreKey, McastRole> roles = mcastRoleStore.entrySet().stream()
-                    .filter(mcastEntry -> mcastIp.equals(mcastEntry.getKey().mcastIp()))
-                    .collect(Collectors.toMap(entry -> new McastRoleStoreKey(entry.getKey().mcastIp(),
-                     entry.getKey().deviceId(), entry.getKey().source()), entry -> entry.getValue().value()));
-            if (sourcecp != null) {
-                roles = roles.entrySet().stream()
-                        .filter(mcastEntry -> sourcecp.equals(mcastEntry.getKey().source()))
-                        .collect(Collectors.toMap(entry -> new McastRoleStoreKey(entry.getKey().mcastIp(),
-                         entry.getKey().deviceId(), entry.getKey().source()), Entry::getValue));
-            }
-            return roles;
-        }
-        return mcastRoleStore.entrySet().stream()
-                .collect(Collectors.toMap(entry -> new McastRoleStoreKey(entry.getKey().mcastIp(),
-                 entry.getKey().deviceId(), entry.getKey().source()), entry -> entry.getValue().value()));
-    }
-
-    /**
-     * Returns the associated trees to the mcast group.
-     *
-     * @param mcastIp the group ip
-     * @param sourcecp the source connect point
-     * @return the mapping egress point to mcast path
-     */
-    public Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
-                                                                    ConnectPoint sourcecp) {
-        // TODO remove
-        log.info("{}", getStoredPaths(mcastIp));
-        Multimap<ConnectPoint, List<ConnectPoint>> mcastTrees = HashMultimap.create();
-        Set<ConnectPoint> sources = mcastUtils.getSources(mcastIp);
-        if (sourcecp != null) {
-            sources = sources.stream()
-                    .filter(source -> source.equals(sourcecp)).collect(Collectors.toSet());
-        }
-        if (!sources.isEmpty()) {
-            sources.forEach(source -> {
-                McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
-                Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
-                        mcastPathStore.get(pathStoreKey), Lists.newArrayList());
-                // TODO remove
-                log.info("Paths for group {} and source {} - {}", mcastIp, source, storedPaths.size());
-                Map<ConnectPoint, List<ConnectPoint>> mcastTree = buildMcastPaths(storedPaths, mcastIp, source);
-                mcastTree.forEach(mcastTrees::put);
-            });
-        }
-        return mcastTrees;
-    }
-
-    /**
-     * Return the leaders of the mcast groups.
-     *
-     * @param mcastIp the group ip
-     * @return the mapping group-node
-     */
-    public Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp) {
-        return mcastUtils.getMcastLeaders(mcastIp);
-    }
-
-    /**
-     * Returns the mcast filtering obj.
-     *
-     * @return the mapping group-node
-     */
-    public Map<DeviceId, List<McastFilteringObjStoreKey>> getMcastFilters() {
-        // TODO remove
-        log.info("mcastFilters {}", mcastFilteringObjStore.size());
-        Map<DeviceId, List<McastFilteringObjStoreKey>> mapping = Maps.newHashMap();
-        Set<McastFilteringObjStoreKey> currentKeys = Sets.newHashSet(mcastFilteringObjStore);
-        currentKeys.forEach(filteringObjStoreKey ->
-            mapping.compute(filteringObjStoreKey.ingressCP().deviceId(), (k, v) -> {
-                List<McastFilteringObjStoreKey> values = v;
-                if (values == null) {
-                    values = Lists.newArrayList();
-                }
-                values.add(filteringObjStoreKey);
-                return values;
-            })
-        );
-        return mapping;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java
deleted file mode 100644
index 76f46fe..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Key of multicast path store.
- */
-public class McastPathStoreKey {
-    // Identify path using group address and source
-    private final IpAddress mcastIp;
-    private final ConnectPoint source;
-
-    /**
-     * Constructs the key of multicast path store.
-     *
-     * @param mcastIp multicast group IP address
-     * @param source source connect point
-     */
-    public McastPathStoreKey(IpAddress mcastIp, ConnectPoint source) {
-        checkNotNull(mcastIp, "mcastIp cannot be null");
-        checkNotNull(source, "source cannot be null");
-        checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
-        this.mcastIp = mcastIp;
-        this.source = source;
-    }
-
-    // Constructor for serialization
-    private McastPathStoreKey() {
-        this.mcastIp = null;
-        this.source = null;
-    }
-
-    /**
-     * Returns the multicast IP address of this key.
-     *
-     * @return multicast IP
-     */
-    public IpAddress mcastIp() {
-        return mcastIp;
-    }
-
-    /**
-     * Returns the device ID of this key.
-     *
-     * @return device ID
-     */
-    public ConnectPoint source() {
-        return source;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof McastPathStoreKey)) {
-            return false;
-        }
-        McastPathStoreKey that =
-                (McastPathStoreKey) o;
-        return (Objects.equals(this.mcastIp, that.mcastIp) &&
-                Objects.equals(this.source, that.source));
-    }
-
-    @Override
-    public int hashCode() {
-         return Objects.hash(mcastIp, source);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("mcastIp", mcastIp)
-                .add("source", source)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java
deleted file mode 100644
index 4ef0194..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-
-/**
- * Custom serializer for {@link McastPathStoreKey}.
- */
-class McastPathStoreKeySerializer extends Serializer<McastPathStoreKey> {
-
-    /**
-     * Creates {@link McastPathStoreKeySerializer} serializer instance.
-     */
-    McastPathStoreKeySerializer() {
-        // non-null, immutable
-        super(false, true);
-    }
-
-    @Override
-    public void write(Kryo kryo, Output output, McastPathStoreKey object) {
-        kryo.writeClassAndObject(output, object.mcastIp());
-        kryo.writeClassAndObject(output, object.source());
-    }
-
-    @Override
-    public McastPathStoreKey read(Kryo kryo, Input input, Class<McastPathStoreKey> type) {
-        IpAddress mcastIp = (IpAddress) kryo.readClassAndObject(input);
-        ConnectPoint source = (ConnectPoint) kryo.readClassAndObject(input);
-        return new McastPathStoreKey(mcastIp, source);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRole.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRole.java
deleted file mode 100644
index 454bb5c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRole.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-/**
- * Enum that defines role in the multicast tree.
- */
-public enum McastRole {
-    /**
-     * The device is the ingress device of this group.
-     */
-    INGRESS,
-    /**
-     * The device is the transit device of this group.
-     */
-    TRANSIT,
-    /**
-     * The device is the egress device of this group.
-     */
-    EGRESS
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKey.java
deleted file mode 100644
index 26f21f2..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKey.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Key of multicast role store.
- */
-public class McastRoleStoreKey {
-    // Identify role using group address, deviceId and source
-    private final IpAddress mcastIp;
-    private final DeviceId deviceId;
-    private final ConnectPoint source;
-
-    /**
-     * Constructs the key of multicast role store.
-     *
-     * @param mcastIp multicast group IP address
-     * @param deviceId device ID
-     * @param source source connect point
-     */
-    public McastRoleStoreKey(IpAddress mcastIp, DeviceId deviceId, ConnectPoint source) {
-        checkNotNull(mcastIp, "mcastIp cannot be null");
-        checkNotNull(deviceId, "deviceId cannot be null");
-        checkNotNull(source, "source cannot be null");
-        checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
-        this.mcastIp = mcastIp;
-        this.deviceId = deviceId;
-        this.source = source;
-    }
-
-    // Constructor for serialization
-    private McastRoleStoreKey() {
-        this.mcastIp = null;
-        this.deviceId = null;
-        this.source = null;
-    }
-
-    /**
-     * Returns the multicast IP address of this key.
-     *
-     * @return multicast IP
-     */
-    public IpAddress mcastIp() {
-        return mcastIp;
-    }
-
-    /**
-     * Returns the device ID of this key.
-     *
-     * @return device ID
-     */
-    public DeviceId deviceId() {
-        return deviceId;
-    }
-
-    /**
-     * Returns the source connect point of this key.
-     *
-     * @return the source connect point
-     */
-    public ConnectPoint source() {
-        return source;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof McastRoleStoreKey)) {
-            return false;
-        }
-        final McastRoleStoreKey that = (McastRoleStoreKey) o;
-
-        return Objects.equals(this.mcastIp, that.mcastIp) &&
-                Objects.equals(this.deviceId, that.deviceId) &&
-                Objects.equals(this.source, that.source);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mcastIp, deviceId, source);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("mcastIp", mcastIp)
-                .add("deviceId", deviceId)
-                .add("source", source)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKeySerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKeySerializer.java
deleted file mode 100644
index aec7278..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKeySerializer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-/**
- * Custom serializer for {@link McastRoleStoreKey}.
- */
-class McastRoleStoreKeySerializer extends Serializer<McastRoleStoreKey> {
-
-    /**
-     * Creates {@link McastRoleStoreKeySerializer} serializer instance.
-     */
-    McastRoleStoreKeySerializer() {
-        // non-null, immutable
-        super(false, true);
-    }
-
-    @Override
-    public void write(Kryo kryo, Output output, McastRoleStoreKey object) {
-        kryo.writeClassAndObject(output, object.mcastIp());
-        output.writeString(object.deviceId().toString());
-        kryo.writeClassAndObject(output, object.source());
-    }
-
-    @Override
-    public McastRoleStoreKey read(Kryo kryo, Input input, Class<McastRoleStoreKey> type) {
-        IpAddress mcastIp = (IpAddress) kryo.readClassAndObject(input);
-        final String str = input.readString();
-        DeviceId deviceId =  DeviceId.deviceId(str);
-        ConnectPoint source = (ConnectPoint) kryo.readClassAndObject(input);
-        return new McastRoleStoreKey(mcastIp, deviceId, source);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKey.java
deleted file mode 100644
index aa32797..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKey.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import java.util.Objects;
-
-/**
- * Key of multicast next objective store.
- */
-public class McastStoreKey {
-    // Identify a flow using group address, deviceId, and assigned vlan
-    private final IpAddress mcastIp;
-    private final DeviceId deviceId;
-    private final VlanId vlanId;
-
-    /**
-     * Constructs the key of multicast next objective store.
-     *
-     * @param mcastIp multicast group IP address
-     * @param deviceId device ID
-     *
-     * @deprecated in 1.12 ("Magpie") release.
-     */
-    @Deprecated
-    public McastStoreKey(IpAddress mcastIp, DeviceId deviceId) {
-        checkNotNull(mcastIp, "mcastIp cannot be null");
-        checkNotNull(deviceId, "deviceId cannot be null");
-        checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
-        this.mcastIp = mcastIp;
-        this.deviceId = deviceId;
-        this.vlanId = null;
-    }
-
-    /**
-     * Constructs the key of multicast next objective store.
-     *
-     * @param mcastIp multicast group IP address
-     * @param deviceId device ID
-     * @param vlanId vlan id
-     */
-    public McastStoreKey(IpAddress mcastIp, DeviceId deviceId, VlanId vlanId) {
-        checkNotNull(mcastIp, "mcastIp cannot be null");
-        checkNotNull(deviceId, "deviceId cannot be null");
-        checkNotNull(vlanId, "vlan id cannot be null");
-        checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
-        this.mcastIp = mcastIp;
-        this.deviceId = deviceId;
-        // FIXME probably we should avoid not valid values
-        this.vlanId = vlanId;
-    }
-
-    // Constructor for serialization
-    private McastStoreKey() {
-        this.mcastIp = null;
-        this.deviceId = null;
-        this.vlanId = null;
-    }
-
-    /**
-     * Returns the multicast IP address of this key.
-     *
-     * @return multicast IP
-     */
-    public IpAddress mcastIp() {
-        return mcastIp;
-    }
-
-    /**
-     * Returns the device ID of this key.
-     *
-     * @return device ID
-     */
-    public DeviceId deviceId() {
-        return deviceId;
-    }
-
-    /**
-     * Returns the vlan ID of this key.
-     *
-     * @return vlan ID
-     */
-    public VlanId vlanId() {
-        return vlanId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof McastStoreKey)) {
-            return false;
-        }
-        McastStoreKey that =
-                (McastStoreKey) o;
-        return (Objects.equals(this.mcastIp, that.mcastIp) &&
-                Objects.equals(this.deviceId, that.deviceId) &&
-                Objects.equals(this.vlanId, that.vlanId));
-    }
-
-    @Override
-    public int hashCode() {
-         return Objects.hash(mcastIp, deviceId, vlanId);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("mcastIp", mcastIp)
-                .add("deviceId", deviceId)
-                .add("vlanId", vlanId)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKeySerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKeySerializer.java
deleted file mode 100644
index c32b0ba..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKeySerializer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-/**
- * Custom serializer for {@link McastStoreKey}.
- */
-class McastStoreKeySerializer extends Serializer<McastStoreKey> {
-
-    /**
-     * Creates {@link McastStoreKeySerializer} serializer instance.
-     */
-    McastStoreKeySerializer() {
-        // non-null, immutable
-        super(false, true);
-    }
-
-    @Override
-    public void write(Kryo kryo, Output output, McastStoreKey object) {
-        kryo.writeClassAndObject(output, object.mcastIp());
-        output.writeString(object.deviceId().toString());
-        kryo.writeClassAndObject(output, object.vlanId());
-    }
-
-    @Override
-    public McastStoreKey read(Kryo kryo, Input input, Class<McastStoreKey> type) {
-        IpAddress mcastIp = (IpAddress) kryo.readClassAndObject(input);
-        final String str = input.readString();
-        DeviceId deviceId =  DeviceId.deviceId(str);
-        VlanId vlanId = (VlanId) kryo.readClassAndObject(input);
-        return new McastStoreKey(mcastIp, deviceId, vlanId);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
deleted file mode 100644
index 396b998..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-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 com.google.common.hash.HashFunction;
-import com.google.common.hash.Hashing;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.basics.McastConfig;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.topology.LinkWeigher;
-import org.onosproject.net.topology.Topology;
-import org.onosproject.net.topology.TopologyService;
-import org.onosproject.segmentrouting.SRLinkWeigher;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Utility class for Multicast Handler.
- */
-class McastUtils {
-    // Internal reference to the log
-    private final Logger log;
-    // Internal reference to SR Manager and topology service
-    private final SegmentRoutingManager srManager;
-    private final TopologyService topologyService;
-    // Internal reference to the app id
-    private ApplicationId coreAppId;
-    // Hashing function for the multicast hasher
-    private static final HashFunction HASH_FN = Hashing.md5();
-    // Read only cache of the Mcast leader
-    private Map<IpAddress, NodeId> mcastLeaderCache;
-
-    /**
-     * Builds a new McastUtils object.
-     *
-     * @param srManager the SR manager
-     * @param coreAppId the core application id
-     * @param log log reference of the McastHandler
-     */
-    McastUtils(SegmentRoutingManager srManager, ApplicationId coreAppId, Logger log) {
-        this.srManager = srManager;
-        this.topologyService = srManager.topologyService;
-        this.coreAppId = coreAppId;
-        this.log = log;
-        this.mcastLeaderCache = Maps.newConcurrentMap();
-    }
-
-    /**
-     * Clean up when deactivating the application.
-     */
-    void terminate() {
-        mcastLeaderCache.clear();
-    }
-
-    /**
-     * Get router mac using application config and the connect point.
-     *
-     * @param deviceId the device id
-     * @param port the port number
-     * @return the router mac if the port is configured, otherwise null
-     */
-    private MacAddress getRouterMac(DeviceId deviceId, PortNumber port) {
-        // Do nothing if the port is configured as suppressed
-        ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
-        SegmentRoutingAppConfig appConfig = srManager.cfgService
-                .getConfig(srManager.appId(), SegmentRoutingAppConfig.class);
-        if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
-            log.info("Ignore suppressed port {}", connectPoint);
-            return MacAddress.NONE;
-        }
-        // Get the router mac using the device configuration
-        MacAddress routerMac;
-        try {
-            routerMac = srManager.deviceConfiguration().getDeviceMac(deviceId);
-        } catch (DeviceConfigNotFoundException dcnfe) {
-            log.warn("Failed to get device MAC since the device {} is not configured", deviceId);
-            return null;
-        }
-        return routerMac;
-    }
-
-    /**
-     * Adds filtering objective for given device and port.
-     *
-     * @param deviceId device ID
-     * @param port ingress port number
-     * @param assignedVlan assigned VLAN ID
-     * @param mcastIp the group address
-     * @param mcastRole the role of the device
-     * @param matchOnMac match or not on macaddress
-     */
-    void addFilterToDevice(DeviceId deviceId, PortNumber port, VlanId assignedVlan,
-                           IpAddress mcastIp, McastRole mcastRole, boolean matchOnMac) {
-        if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-            log.debug("skip update of fitering objective for unconfigured device: {}", deviceId);
-            return;
-        }
-        MacAddress routerMac = getRouterMac(deviceId, port);
-
-        if (MacAddress.NONE.equals(routerMac)) {
-            return;
-        }
-        FilteringObjective.Builder filtObjBuilder = filterObjBuilder(port, assignedVlan, mcastIp,
-                                                                     routerMac, mcastRole, matchOnMac);
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Successfully add filter on {}/{}, vlan {}",
-                                         deviceId, port.toLong(), assignedVlan),
-                (objective, error) ->
-                        log.warn("Failed to add filter on {}/{}, vlan {}: {}",
-                                 deviceId, port.toLong(), assignedVlan, error));
-        srManager.flowObjectiveService.filter(deviceId, filtObjBuilder.add(context));
-    }
-
-    /**
-     * Removes filtering objective for given device and port.
-     *
-     * @param deviceId device ID
-     * @param port ingress port number
-     * @param assignedVlan assigned VLAN ID
-     * @param mcastIp multicast IP address
-     * @param mcastRole the multicast role of the device
-     */
-    void removeFilterToDevice(DeviceId deviceId, PortNumber port, VlanId assignedVlan,
-                              IpAddress mcastIp, McastRole mcastRole) {
-        if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
-            log.debug("skip update of fitering objective for unconfigured device: {}", deviceId);
-            return;
-        }
-        MacAddress routerMac = getRouterMac(deviceId, port);
-
-        if (MacAddress.NONE.equals(routerMac)) {
-            return;
-        }
-        FilteringObjective.Builder filtObjBuilder =
-                filterObjBuilder(port, assignedVlan, mcastIp, routerMac, mcastRole, false);
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Successfully removed filter on {}/{}, vlan {}",
-                                         deviceId, port.toLong(), assignedVlan),
-                (objective, error) ->
-                        log.warn("Failed to remove filter on {}/{}, vlan {}: {}",
-                                 deviceId, port.toLong(), assignedVlan, error));
-        srManager.flowObjectiveService.filter(deviceId, filtObjBuilder.remove(context));
-    }
-
-    /**
-     * Gets ingress VLAN from McastConfig.
-     *
-     * @return ingress VLAN or VlanId.NONE if not configured
-     */
-    private VlanId ingressVlan() {
-        McastConfig mcastConfig =
-                srManager.cfgService.getConfig(coreAppId, McastConfig.class);
-        return (mcastConfig != null) ? mcastConfig.ingressVlan() : VlanId.NONE;
-    }
-
-    /**
-     * Gets egress VLAN from McastConfig.
-     *
-     * @return egress VLAN or VlanId.NONE if not configured
-     */
-    private VlanId egressVlan() {
-        McastConfig mcastConfig =
-                srManager.cfgService.getConfig(coreAppId, McastConfig.class);
-        return (mcastConfig != null) ? mcastConfig.egressVlan() : VlanId.NONE;
-    }
-
-    /**
-     * Gets assigned VLAN according to the value of egress VLAN.
-     * If connect point is specified, try to reuse the assigned VLAN on the connect point.
-     *
-     * @param cp connect point; Can be null if not specified
-     * @return assigned VLAN ID
-     */
-    VlanId assignedVlan(ConnectPoint cp) {
-        // Use the egressVlan if it is tagged
-        if (!egressVlan().equals(VlanId.NONE)) {
-            return egressVlan();
-        }
-        // Reuse unicast VLAN if the port has subnet configured
-        if (cp != null) {
-            VlanId untaggedVlan = srManager.getInternalVlanId(cp);
-            return (untaggedVlan != null) ? untaggedVlan
-                                          : srManager.getDefaultInternalVlan();
-        }
-        // Use DEFAULT_VLAN if none of the above matches
-        return srManager.getDefaultInternalVlan();
-    }
-
-
-
-    /**
-     * Gets sources connect points of given multicast group.
-     *
-     * @param mcastIp multicast IP
-     * @return sources connect points or empty set if not found
-     */
-    Set<ConnectPoint> getSources(IpAddress mcastIp) {
-        // TODO we should support different types of routes
-        McastRoute mcastRoute = srManager.multicastRouteService.getRoutes().stream()
-                .filter(mcastRouteInternal -> mcastRouteInternal.group().equals(mcastIp))
-                .findFirst().orElse(null);
-        return mcastRoute == null ? ImmutableSet.of() :
-                srManager.multicastRouteService.sources(mcastRoute);
-    }
-
-    /**
-     * Gets sinks of given multicast group.
-     *
-     * @param mcastIp multicast IP
-     * @return map of sinks or empty map if not found
-     */
-    Map<HostId, Set<ConnectPoint>> getSinks(IpAddress mcastIp) {
-        // TODO we should support different types of routes
-        McastRoute mcastRoute = srManager.multicastRouteService.getRoutes().stream()
-                .filter(mcastRouteInternal -> mcastRouteInternal.group().equals(mcastIp))
-                .findFirst().orElse(null);
-        return mcastRoute == null ?
-                ImmutableMap.of() :
-                srManager.multicastRouteService.routeData(mcastRoute).sinks();
-    }
-
-    /**
-     * Get sinks affected by this egress device.
-     *
-     * @param egressDevice the egress device
-     * @param mcastIp the mcast ip address
-     * @return the map of the sinks affected
-     */
-    Map<HostId, Set<ConnectPoint>> getAffectedSinks(DeviceId egressDevice,
-                                                    IpAddress mcastIp) {
-        return getSinks(mcastIp).entrySet()
-                .stream()
-                .filter(hostIdSetEntry -> hostIdSetEntry.getValue().stream()
-                        .map(ConnectPoint::deviceId)
-                        .anyMatch(deviceId -> deviceId.equals(egressDevice))
-                ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
-    }
-
-    /**
-     * Creates a next objective builder for multicast.
-     *
-     * @param mcastIp multicast group
-     * @param assignedVlan assigned VLAN ID
-     * @param outPorts set of output port numbers
-     * @param nextId the next id
-     * @return next objective builder
-     */
-    NextObjective.Builder nextObjBuilder(IpAddress mcastIp, VlanId assignedVlan,
-                                         Set<PortNumber> outPorts, Integer nextId) {
-        // If nextId is null allocate a new one
-        if (nextId == null) {
-            nextId = srManager.flowObjectiveService.allocateNextId();
-        }
-        // Build the meta selector with the fwd objective info
-        TrafficSelector metadata =
-                DefaultTrafficSelector.builder()
-                        .matchVlanId(assignedVlan)
-                        .matchIPDst(mcastIp.toIpPrefix())
-                        .build();
-        // Define the nextobjective type
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.BROADCAST)
-                .fromApp(srManager.appId())
-                .withMeta(metadata);
-        // Add the output ports
-        outPorts.forEach(port -> {
-            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-            if (egressVlan().equals(VlanId.NONE)) {
-                tBuilder.popVlan();
-            }
-            tBuilder.setOutput(port);
-            nextObjBuilder.addTreatment(tBuilder.build());
-        });
-        // Done return the complete builder
-        return nextObjBuilder;
-    }
-
-    /**
-     * Creates a forwarding objective builder for multicast.
-     *
-     * @param mcastIp multicast group
-     * @param assignedVlan assigned VLAN ID
-     * @param nextId next ID of the L3 multicast group
-     * @return forwarding objective builder
-     */
-    ForwardingObjective.Builder fwdObjBuilder(IpAddress mcastIp,
-                                                      VlanId assignedVlan, int nextId) {
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        // Let's the matching on the group address
-        // TODO SSM support in future
-        if (mcastIp.isIp6()) {
-            sbuilder.matchEthType(Ethernet.TYPE_IPV6);
-            sbuilder.matchIPv6Dst(mcastIp.toIpPrefix());
-        } else {
-            sbuilder.matchEthType(Ethernet.TYPE_IPV4);
-            sbuilder.matchIPDst(mcastIp.toIpPrefix());
-        }
-        // Then build the meta selector
-        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
-        metabuilder.matchVlanId(assignedVlan);
-        // Finally return the completed builder
-        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder();
-        fwdBuilder.withSelector(sbuilder.build())
-                .withMeta(metabuilder.build())
-                .nextStep(nextId)
-                .withFlag(ForwardingObjective.Flag.SPECIFIC)
-                .fromApp(srManager.appId())
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
-        return fwdBuilder;
-    }
-
-    /**
-     * Creates a filtering objective builder for multicast.
-     *
-     * @param ingressPort ingress port of the multicast stream
-     * @param assignedVlan assigned VLAN ID
-     * @param mcastIp the group address
-     * @param routerMac router MAC. This is carried in metadata and used from some switches that
-     *                  need to put unicast entry before multicast entry in TMAC table.
-     * @param mcastRole the Multicast role
-     * @param matchOnMac match or not on macaddress
-     * @return filtering objective builder
-     */
-    private FilteringObjective.Builder filterObjBuilder(PortNumber ingressPort, VlanId assignedVlan,
-                                                        IpAddress mcastIp, MacAddress routerMac, McastRole mcastRole,
-                                                        boolean matchOnMac) {
-        FilteringObjective.Builder filtBuilder = DefaultFilteringObjective.builder();
-        // Let's add the in port matching and the priority
-        filtBuilder.withKey(Criteria.matchInPort(ingressPort))
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
-        // According to the mcast role we match on the proper vlan
-        // If the role is null we are on the transit or on the egress
-        if (mcastRole == null) {
-            filtBuilder.addCondition(Criteria.matchVlanId(egressVlan()));
-        } else {
-            filtBuilder.addCondition(Criteria.matchVlanId(ingressVlan()));
-        }
-        // Add vlan info to the treatment builder
-        TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder()
-                .pushVlan().setVlanId(assignedVlan);
-        // Additionally match on mac address and augment the treatment
-        if (matchOnMac) {
-            // According to the IP type we set the proper match on the mac address
-            if (mcastIp.isIp4()) {
-                filtBuilder.addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST,
-                        MacAddress.IPV4_MULTICAST_MASK));
-            } else {
-                filtBuilder.addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST,
-                        MacAddress.IPV6_MULTICAST_MASK));
-            }
-            // We set mac address to the treatment
-            if (routerMac != null && !routerMac.equals(MacAddress.NONE)) {
-                ttb.setEthDst(routerMac);
-            }
-        }
-        // We finally build the meta treatment
-        TrafficTreatment tt = ttb.build();
-        filtBuilder.withMeta(tt);
-        // Done, we return a permit filtering objective
-        return filtBuilder.permit().fromApp(srManager.appId());
-    }
-
-    /**
-     * Gets output ports information from treatments.
-     *
-     * @param treatments collection of traffic treatments
-     * @return set of output port numbers
-     */
-    Set<PortNumber> getPorts(Collection<TrafficTreatment> treatments) {
-        ImmutableSet.Builder<PortNumber> builder = ImmutableSet.builder();
-        treatments.forEach(treatment -> treatment.allInstructions().stream()
-                    .filter(instr -> instr instanceof Instructions.OutputInstruction)
-                    .forEach(instr -> builder.add(((Instructions.OutputInstruction) instr).port())));
-        return builder.build();
-    }
-
-    /**
-     * Returns the hash of the group address.
-     *
-     * @param ipAddress the ip address
-     * @return the hash of the address
-     */
-    private Long hasher(IpAddress ipAddress) {
-        return HASH_FN.newHasher()
-                .putBytes(ipAddress.toOctets())
-                .hash()
-                .asLong();
-    }
-
-    /**
-     * Given a multicast group define a leader for it.
-     *
-     * @param mcastIp the group address
-     * @return true if the instance is the leader of the group
-     */
-    boolean isLeader(IpAddress mcastIp) {
-        // Get our id
-        final NodeId currentNodeId = srManager.clusterService.getLocalNode().id();
-        // Get the leader for this group using the ip address as key
-        final NodeId leader = srManager.workPartitionService.getLeader(mcastIp, this::hasher);
-        // If there is not a leader, let's send an error
-        if (leader == null) {
-            log.error("Fail to elect a leader for {}.", mcastIp);
-            return false;
-        }
-        // Update cache and return operation result
-        mcastLeaderCache.put(mcastIp, leader);
-        return currentNodeId.equals(leader);
-    }
-
-    /**
-     * Given a multicast group withdraw its leader.
-     *
-     * @param mcastIp the group address
-     */
-    void withdrawLeader(IpAddress mcastIp) {
-        // For now just update the cache
-        mcastLeaderCache.remove(mcastIp);
-    }
-
-    Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp) {
-        // If mcast ip is present
-        if (mcastIp != null) {
-            return mcastLeaderCache.entrySet().stream()
-                    .filter(entry -> entry.getKey().equals(mcastIp))
-                    .collect(Collectors.toMap(Map.Entry::getKey,
-                                              Map.Entry::getValue));
-        }
-        // Otherwise take all the groups
-        return ImmutableMap.copyOf(mcastLeaderCache);
-    }
-
-    /**
-     * Go through all the paths, looking for shared links to be used
-     * in the final path computation.
-     *
-     * @param egresses egress devices
-     * @param availablePaths all the available paths towards the egress
-     * @return shared links between egress devices
-     */
-    private Set<Link> exploreMcastTree(Set<DeviceId> egresses,
-                                       Map<DeviceId, List<Path>> availablePaths) {
-        int minLength = Integer.MAX_VALUE;
-        int length;
-        List<Path> currentPaths;
-        // Verify the source can still reach all the egresses
-        for (DeviceId egress : egresses) {
-            // From the source we cannot reach all the sinks
-            // just continue and let's figure out after
-            currentPaths = availablePaths.get(egress);
-            if (currentPaths.isEmpty()) {
-                continue;
-            }
-            // Get the length of the first one available, update the min length
-            length = currentPaths.get(0).links().size();
-            if (length < minLength) {
-                minLength = length;
-            }
-        }
-        // If there are no paths
-        if (minLength == Integer.MAX_VALUE) {
-            return Collections.emptySet();
-        }
-        int index = 0;
-        Set<Link> sharedLinks = Sets.newHashSet();
-        Set<Link> currentSharedLinks;
-        Set<Link> currentLinks;
-        DeviceId egressToRemove = null;
-        // Let's find out the shared links
-        while (index < minLength) {
-            // Initialize the intersection with the paths related to the first egress
-            currentPaths = availablePaths.get(egresses.stream().findFirst().orElse(null));
-            currentSharedLinks = Sets.newHashSet();
-            // Iterate over the paths and take the "index" links
-            for (Path path : currentPaths) {
-                currentSharedLinks.add(path.links().get(index));
-            }
-            // Iterate over the remaining egress
-            for (DeviceId egress : egresses) {
-                // Iterate over the paths and take the "index" links
-                currentLinks = Sets.newHashSet();
-                for (Path path : availablePaths.get(egress)) {
-                    currentLinks.add(path.links().get(index));
-                }
-                // Do intersection
-                currentSharedLinks = Sets.intersection(currentSharedLinks, currentLinks);
-                // If there are no shared paths exit and record the device to remove
-                // we have to retry with a subset of sinks
-                if (currentSharedLinks.isEmpty()) {
-                    egressToRemove = egress;
-                    index = minLength;
-                    break;
-                }
-            }
-            sharedLinks.addAll(currentSharedLinks);
-            index++;
-        }
-        // If the shared links is empty and there are egress let's retry another time with less sinks,
-        // we can still build optimal subtrees
-        if (sharedLinks.isEmpty() && egresses.size() > 1 && egressToRemove != null) {
-            egresses.remove(egressToRemove);
-            sharedLinks = exploreMcastTree(egresses, availablePaths);
-        }
-        return sharedLinks;
-    }
-
-    /**
-     * Build Mcast tree having as root the given source and as leaves the given egress points.
-     *
-     * @param mcastIp multicast group
-     * @param source source of the tree
-     * @param sinks leaves of the tree
-     * @return the computed Mcast tree
-     */
-    Map<ConnectPoint, List<Path>> computeSinkMcastTree(IpAddress mcastIp,
-                                                       DeviceId source,
-                                                       Set<ConnectPoint> sinks) {
-        // Get the egress devices, remove source from the egress if present
-        Set<DeviceId> egresses = sinks.stream().map(ConnectPoint::deviceId)
-                .filter(deviceId -> !deviceId.equals(source)).collect(Collectors.toSet());
-        Map<DeviceId, List<Path>> mcastTree = computeMcastTree(mcastIp, source, egresses);
-        final Map<ConnectPoint, List<Path>> finalTree = Maps.newHashMap();
-        // We need to put back the source if it was originally present
-        sinks.forEach(sink -> {
-            List<Path> sinkPaths = mcastTree.get(sink.deviceId());
-            finalTree.put(sink, sinkPaths != null ? sinkPaths : ImmutableList.of());
-        });
-        return finalTree;
-    }
-
-    /**
-     * Build Mcast tree having as root the given source and as leaves the given egress.
-     *
-     * @param mcastIp multicast group
-     * @param source source of the tree
-     * @param egresses leaves of the tree
-     * @return the computed Mcast tree
-     */
-    private Map<DeviceId, List<Path>> computeMcastTree(IpAddress mcastIp,
-                                                       DeviceId source,
-                                                       Set<DeviceId> egresses) {
-        log.debug("Computing tree for Multicast group {}, source {} and leafs {}",
-                  mcastIp, source, egresses);
-        // Pre-compute all the paths
-        Map<DeviceId, List<Path>> availablePaths = Maps.newHashMap();
-        egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
-                                                                       Collections.emptySet())));
-        // Explore the topology looking for shared links amongst the egresses
-        Set<Link> linksToEnforce = exploreMcastTree(Sets.newHashSet(egresses), availablePaths);
-        // Build the final paths enforcing the shared links between egress devices
-        availablePaths.clear();
-        egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
-                                                                       linksToEnforce)));
-        return availablePaths;
-    }
-
-    /**
-     * Gets path from src to dst computed using the custom link weigher.
-     *
-     * @param src source device ID
-     * @param dst destination device ID
-     * @param linksToEnforce links to be enforced
-     * @return list of paths from src to dst
-     */
-    List<Path> getPaths(DeviceId src, DeviceId dst, Set<Link> linksToEnforce) {
-        final Topology currentTopology = topologyService.currentTopology();
-        final LinkWeigher linkWeigher = new SRLinkWeigher(srManager, src, linksToEnforce);
-        List<Path> allPaths = Lists.newArrayList(topologyService.getPaths(currentTopology, src, dst, linkWeigher));
-        log.trace("{} path(s) found from {} to {}", allPaths.size(), src, dst);
-        return allPaths;
-    }
-
-    /**
-     * Gets a stored path having dst as egress.
-     *
-     * @param dst destination device ID
-     * @param storedPaths paths list
-     * @return an optional path
-     */
-    Optional<? extends List<Link>> getStoredPath(DeviceId dst, Collection<? extends List<Link>> storedPaths) {
-        return storedPaths.stream()
-                .filter(path -> path.get(path.size() - 1).dst().deviceId().equals(dst))
-                .findFirst();
-    }
-
-    /**
-     * Returns a set of affected paths by the failed element.
-     *
-     * @param paths the paths to check
-     * @param failedElement the failed element
-     * @return the affected paths
-     */
-    Set<List<Link>> getAffectedPaths(Set<List<Link>> paths, Object failedElement) {
-        if (failedElement instanceof DeviceId) {
-            return getAffectedPathsByDevice(paths, failedElement);
-        }
-        return getAffectedPathsByLink(paths, failedElement);
-    }
-
-    private Set<List<Link>> getAffectedPathsByDevice(Set<List<Link>> paths, Object failedElement) {
-        DeviceId affectedDevice = (DeviceId) failedElement;
-        Set<List<Link>> affectedPaths = Sets.newHashSet();
-        paths.forEach(path -> {
-            if (path.stream().anyMatch(link -> link.src().deviceId().equals(affectedDevice))) {
-                affectedPaths.add(path);
-            }
-        });
-        return affectedPaths;
-    }
-
-    private Set<List<Link>> getAffectedPathsByLink(Set<List<Link>> paths, Object failedElement) {
-        Link affectedLink = (Link) failedElement;
-        Set<List<Link>> affectedPaths = Sets.newHashSet();
-        paths.forEach(path -> {
-            if (path.contains(affectedLink)) {
-                affectedPaths.add(path);
-            }
-        });
-        return affectedPaths;
-    }
-
-    /**
-     * Checks if the failure is affecting the transit device.
-     *
-     * @param devices the transit devices
-     * @param failedElement the failed element
-     * @return true if the failed element is affecting the transit devices
-     */
-    boolean isInfraFailure(Set<DeviceId> devices, Object failedElement) {
-        if (failedElement instanceof DeviceId) {
-            return isInfraFailureByDevice(devices, failedElement);
-        }
-        return true;
-    }
-
-    private boolean isInfraFailureByDevice(Set<DeviceId> devices, Object failedElement) {
-        DeviceId affectedDevice = (DeviceId) failedElement;
-        return devices.contains(affectedDevice);
-    }
-
-    /**
-     * Checks if a port is an infra port.
-     *
-     * @param connectPoint port to be checked
-     * @param storedPaths paths to be checked against
-     * @return true if the port is an infra port. False otherwise.
-     */
-    boolean isInfraPort(ConnectPoint connectPoint, Collection<? extends List<Link>> storedPaths) {
-        for (List<Link> path : storedPaths) {
-            if (path.stream().anyMatch(link -> link.src().equals(connectPoint) ||
-                    link.dst().equals(connectPoint))) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/package-info.java
deleted file mode 100644
index dfdd39a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2018-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.
- */
-
-/**
- * Trellis Multicast service.
- */
-package org.onosproject.segmentrouting.mcast;
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/package-info.java
deleted file mode 100644
index 137ba3c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Segment routing application components.
- */
-package org.onosproject.segmentrouting;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/OsgiPropertyConstants.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/OsgiPropertyConstants.java
deleted file mode 100644
index cdeb8a2..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/OsgiPropertyConstants.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.api;
-
-/**
- * Constants for default values of configurable properties.
- */
-public final class OsgiPropertyConstants {
-    private OsgiPropertyConstants() {}
-
-    public static final String PROP_PHASED_RECOVERY = "phasedRecovery";
-    public static final boolean PHASED_RECOVERY_DEFAULT = false;
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/Phase.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/Phase.java
deleted file mode 100644
index 7f18685..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/Phase.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.api;
-
-/**
- * Phases of recovering devices.
- */
-public enum Phase {
-
-    /**
-     * Device is waiting for ports to be reported.
-     */
-    PENDING,
-
-    /**
-     * Pair port enabled. This is the initial state for paired devices.
-     */
-    PAIR,
-
-    /**
-     * Infrastructure ports enabled.
-     */
-    INFRA,
-
-    /**
-     * Edge ports enabled. This is the initial state for non-paired and spine devices.
-     */
-    EDGE
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/PhasedRecoveryService.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/PhasedRecoveryService.java
deleted file mode 100644
index 705ecb7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/PhasedRecoveryService.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.api;
-
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Service that provides functionality related to phased recovery.
- */
-public interface PhasedRecoveryService {
-
-    // TODO Make timeout values configurable via Component Config Service
-    /**
-     * Timeout for PAIR phase in seconds.
-     */
-    int PAIR_TIMEOUT = 30;
-
-    /**
-     * Timeout for INFRA phase in seconds.
-     */
-    int INFRA_TIMEOUT = 30;
-
-    /**
-     * Timeout for EDGE phase in seconds.
-     */
-    int EDGE_TIMEOUT = 30;
-
-    //
-    // Phased recovery APIs.
-    //
-
-
-    /**
-     * Returns true if phased recovery is enabled.
-     *
-     * @return true if phased recovery is enabled.
-     */
-    boolean isEnabled();
-
-    /**
-     * Initializes a device. Only the master of the device is allowed to do this.
-     *
-     * @param deviceId device ID
-     * @return true if the device is initialized successfully and the caller should proceed,
-     *         false if the device initialization has failed and the caller should abort.
-     */
-    boolean init(DeviceId deviceId);
-
-    /**
-     * Resets a device. Only the master of the device is allowed to do this.
-     *
-     * @param deviceId device ID
-     * @return true if the device is reset successfully.
-     *         false if the device has not been previously initialized.
-     */
-    boolean reset(DeviceId deviceId);
-
-    /**
-     * Gets recovery phase of every devices.
-     *
-     * @return a map between device ID and recovery phase
-     */
-    Map<DeviceId, Phase> getPhases();
-
-    /**
-     * Gets recovery phase of given device.
-     *
-     * @param deviceId device ID
-     * @return current phase or null if the device wasn't seen before
-     */
-    Phase getPhase(DeviceId deviceId);
-
-    /**
-     * Sets given device with given recovery phase. Only the master of the device is allowed to do this.
-     *
-     * @param deviceId device ID
-     * @param newPhase recovery phase
-     * @return new phase if transition succeeded, otherwise return current phase.
-     */
-    Phase setPhase(DeviceId deviceId, Phase newPhase);
-
-    //
-    // Port manipulation APIs.
-    //
-
-    /**
-     * Enables every ports on the given device.
-     *
-     * @param deviceId device id
-     * @param enabled true to enable, false to disable
-     * @return ports that have been enabled
-     */
-    Set<PortNumber> changeAllPorts(DeviceId deviceId, boolean enabled);
-
-    /**
-     * Enables pair port on the given device.
-     *
-     * @param deviceId device id
-     * @param enabled true to enable, false to disable
-     * @return ports that have been enabled
-     */
-    Set<PortNumber> changePairPort(DeviceId deviceId, boolean enabled);
-
-    /**
-     * Enables infrastructure ports on the given device.
-     *
-     * @param deviceId device id
-     * @param enabled true to enable, false to disable
-     * @return ports that have been enabled
-     */
-    Set<PortNumber> changeInfraPorts(DeviceId deviceId, boolean enabled);
-
-    /**
-     * Enables edge ports on the given device.
-     *
-     * @param deviceId device id
-     * @param enabled true to enable, false to disable
-     * @return ports that have been enabled
-     */
-    Set<PortNumber> changeEdgePorts(DeviceId deviceId, boolean enabled);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/package-info.java
deleted file mode 100644
index cc556be..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Phased recovery API.
- */
-package org.onosproject.segmentrouting.phasedrecovery.api;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/PhasedRecoveryManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/PhasedRecoveryManager.java
deleted file mode 100644
index 5e25015..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/PhasedRecoveryManager.java
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.impl;
-
-import com.google.common.collect.Sets;
-import org.onlab.util.KryoNamespace;
-import org.onlab.util.Tools;
-import org.onosproject.cfg.ComponentConfigService;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceAdminService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.Versioned;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Modified;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Dictionary;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.segmentrouting.phasedrecovery.api.OsgiPropertyConstants.PHASED_RECOVERY_DEFAULT;
-import static org.onosproject.segmentrouting.phasedrecovery.api.OsgiPropertyConstants.PROP_PHASED_RECOVERY;
-
-@Component(
-        immediate = true,
-        service = PhasedRecoveryService.class,
-        property = {
-                PROP_PHASED_RECOVERY + ":Boolean=" + PHASED_RECOVERY_DEFAULT
-        }
-)
-public class PhasedRecoveryManager implements PhasedRecoveryService {
-    private static final Logger log = LoggerFactory.getLogger(PhasedRecoveryManager.class);
-    private static final String APP_NAME = "org.onosproject.phasedrecovery";
-
-    // TODO Make these configurable via Component Config
-    // Amount of time delayed to wait for port description (in second)
-    private static final int PORT_CHECKER_INTERVAL = 1;
-    // Max number of retry for port checker
-    private static final int PORT_CHECKER_RETRIES = 5;
-    // RoutingStableChecker interval (in second)
-    private static final int ROUTING_CHECKER_DELAY = 3;
-    // RoutingStableChecker timeout (in second)
-    private static final int ROUTING_CHECKER_TIMEOUT = 15;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private CoreService coreService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private ComponentConfigService compCfgService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private DeviceAdminService deviceAdminService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private MastershipService mastershipService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private StorageService storageService;
-
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL)
-    volatile SegmentRoutingService srService;
-
-    /** Enabling phased recovery. */
-    boolean phasedRecovery = PHASED_RECOVERY_DEFAULT;
-
-    private ApplicationId appId;
-    private ConsistentMap<DeviceId, Phase> phasedRecoveryStore;
-    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(
-            Runtime.getRuntime().availableProcessors(), groupedThreads("onos/sr/pr", "executor"));
-
-    @Activate
-    protected void activate(ComponentContext context) {
-        appId = coreService.registerApplication(APP_NAME);
-
-        KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
-                .register(KryoNamespaces.API)
-                .register(Phase.class);
-        phasedRecoveryStore = storageService.<DeviceId, Phase>consistentMapBuilder()
-                .withName("onos-sr-phasedrecovery")
-                .withRelaxedReadConsistency()
-                .withSerializer(Serializer.using(serializer.build()))
-                .build();
-
-        compCfgService.registerProperties(getClass());
-        modified(context);
-        log.info("Started");
-    }
-
-    @Deactivate
-    protected void deactivate() {
-        phasedRecoveryStore.destroy();
-        compCfgService.unregisterProperties(getClass(), false);
-        log.info("Stopped");
-    }
-
-    @Modified
-    protected void modified(ComponentContext context) {
-        Dictionary<?, ?> properties = context.getProperties();
-        if (properties == null) {
-            return;
-        }
-
-        String strPhasedRecovery = Tools.get(properties, PROP_PHASED_RECOVERY);
-        boolean expectPhasedRecovery = Boolean.parseBoolean(strPhasedRecovery);
-        if (expectPhasedRecovery != phasedRecovery) {
-            phasedRecovery = expectPhasedRecovery;
-            log.info("{} phased recovery", phasedRecovery ? "Enabling" : "Disabling");
-        }
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return phasedRecovery;
-    }
-
-    @Override
-    public boolean init(DeviceId deviceId) {
-        if (this.srService == null) {
-            log.info("SegmentRoutingService is not ready");
-            return false;
-        }
-        if (!mastershipService.isLocalMaster(deviceId)) {
-            log.info("Not master of {}", deviceId);
-            return false;
-        }
-
-        Phase phase = Optional.ofNullable(phasedRecoveryStore.putIfAbsent(deviceId, Phase.PENDING))
-                .map(Versioned::value).orElse(null);
-
-        if (phase != null) {
-            log.info("{} has been initialized already. Skipping.", deviceId);
-            return false;
-        } else {
-            Phase nextPhase = (phasedRecovery && this.srService.getPairDeviceId(deviceId).isPresent()) ?
-                    Phase.PAIR : Phase.EDGE;
-            if (nextPhase == Phase.PAIR) {
-                // Wait for the PORT_STAT before entering next phase.
-                // Note: Unlikely, when the device init fails due to PORT_STATS timeout,
-                //       it requires operator to manually move the device to the next phase by CLI command.
-                executor.schedule(new PortChecker(deviceId, PORT_CHECKER_RETRIES),
-                        PORT_CHECKER_INTERVAL, TimeUnit.SECONDS);
-            } else {
-                // We assume that all ports will be reported as enabled on devices that don't require phased recovery
-                setPhase(deviceId, Phase.EDGE);
-            }
-            return true;
-        }
-    }
-
-    @Override
-    public boolean reset(DeviceId deviceId) {
-        if (this.srService == null) {
-            log.info("SegmentRoutingService is not ready");
-            return false;
-        }
-        // FIXME Skip mastership checking since master will not be available when a device goes offline
-        //       Improve this when persistent mastership is introduced
-
-        Phase result = Optional.ofNullable(phasedRecoveryStore.remove(deviceId))
-                .map(Versioned::value).orElse(null);
-        if (result != null) {
-            log.info("{} is reset", deviceId);
-        }
-        return result != null;
-    }
-
-    @Override
-    public Map<DeviceId, Phase> getPhases() {
-        return phasedRecoveryStore.asJavaMap();
-    }
-
-    @Override
-    public Phase getPhase(DeviceId deviceId) {
-        return Optional.ofNullable(phasedRecoveryStore.get(deviceId)).map(Versioned::value).orElse(null);
-    }
-
-    @Override
-    public Phase setPhase(DeviceId deviceId, Phase newPhase) {
-        if (this.srService == null) {
-            log.info("SegmentRoutingService is not ready");
-            return null;
-        }
-        if (!mastershipService.isLocalMaster(deviceId)) {
-            log.info("Not master of {}", deviceId);
-            return null;
-        }
-
-        return Optional.ofNullable(phasedRecoveryStore.compute(deviceId, (k, v) -> {
-            if (v == null && newPhase == Phase.PENDING) {
-                log.info("Initializing {}", deviceId);
-                return newPhase;
-            } else if (v == Phase.PENDING && newPhase == Phase.PAIR) {
-                srService.initHost(deviceId);
-                // RouteHandler init is intentionally skipped when phased recovery is on.
-                // Edge ports remain down in this phase. Therefore, no nexthop will be discovered on the given device.
-                // The flow on given device will be programmed later by hostHandler.processHostMovedEvent()
-                changePairPort(deviceId, true);
-                log.info("Transitioning {} from PENDING to PAIR", deviceId);
-                return newPhase;
-            } else if (v == Phase.PAIR && newPhase == Phase.INFRA) {
-                changeInfraPorts(deviceId, true);
-                srService.initRoute(deviceId);
-                log.info("Transitioning {} from PAIR to INFRA", deviceId);
-                monitorRoutingStability(deviceId);
-                return newPhase;
-            } else if (v == Phase.INFRA && newPhase == Phase.EDGE) {
-                changeEdgePorts(deviceId, true);
-                log.info("Transitioning {} from INFRA to EDGE", deviceId);
-                return newPhase;
-            } else if (v == Phase.PENDING && newPhase == Phase.EDGE) {
-                changeAllPorts(deviceId, true);
-                srService.initHost(deviceId);
-                srService.initRoute(deviceId);
-                log.info("Transitioning {} from PENDING to EDGE", deviceId);
-                return newPhase;
-            } else {
-                log.debug("Ignore illegal state transition on {} from {} to {}", deviceId, v, newPhase);
-                return v;
-            }
-        })).map(Versioned::value).orElse(null);
-    }
-
-    private void monitorRoutingStability(DeviceId deviceId) {
-        CompletableFuture<Void> checkerFuture = new CompletableFuture<>();
-        CompletableFuture<Void> timeoutFuture =
-                Tools.completeAfter(ROUTING_CHECKER_TIMEOUT, TimeUnit.SECONDS);
-        RoutingStabilityChecker checker = new RoutingStabilityChecker(checkerFuture);
-
-        checkerFuture.runAfterEitherAsync(timeoutFuture, () -> {
-            if (checkerFuture.isDone()) {
-                log.info("Routing stable. Move {} to the next phase", deviceId);
-            } else {
-                log.info("Timeout reached. Move {} to the next phase", deviceId);
-                // Mark the future as completed to signify the termination of periodical checker
-                checkerFuture.complete(null);
-            }
-            setPhase(deviceId, Phase.EDGE);
-        });
-
-        executor.schedule(checker, ROUTING_CHECKER_DELAY, TimeUnit.SECONDS);
-    }
-
-    @Override
-    public Set<PortNumber> changeAllPorts(DeviceId deviceId, boolean enabled) {
-        if (this.srService == null) {
-            log.warn("SegmentRoutingService is not ready. Unable to changeAllPorts({}) to {}", deviceId, enabled);
-            return Sets.newHashSet();
-        }
-        Set<PortNumber> portsToBeEnabled = deviceAdminService.getPorts(deviceId)
-                .stream().map(Port::number).collect(Collectors.toSet());
-        changePorts(deviceId, portsToBeEnabled, enabled);
-        return portsToBeEnabled;
-    }
-
-    @Override
-    public Set<PortNumber> changePairPort(DeviceId deviceId, boolean enabled) {
-        if (this.srService == null) {
-            log.warn("SegmentRoutingService is not ready. Unable to changePairPort({}) to {}", deviceId, enabled);
-            return Sets.newHashSet();
-        }
-        Set<PortNumber> portsToBeEnabled = this.srService.getPairLocalPort(deviceId)
-                .map(Sets::newHashSet).orElse(Sets.newHashSet());
-        changePorts(deviceId, portsToBeEnabled, enabled);
-        return portsToBeEnabled;
-    }
-
-    @Override
-    public Set<PortNumber> changeInfraPorts(DeviceId deviceId, boolean enabled) {
-        if (this.srService == null) {
-            log.warn("SegmentRoutingService is not ready. Unable to changeInfraPorts({}) to {}", deviceId, enabled);
-            return Sets.newHashSet();
-        }
-        Set<PortNumber> portsToBeEnabled = this.srService.getInfraPorts(deviceId);
-        changePorts(deviceId, portsToBeEnabled, enabled);
-        return portsToBeEnabled;
-    }
-
-    @Override
-    public Set<PortNumber> changeEdgePorts(DeviceId deviceId, boolean enabled) {
-        if (this.srService == null) {
-            log.warn("SegmentRoutingService is not ready. Unable to changeEdgePorts({}) to {}", deviceId, enabled);
-            return Sets.newHashSet();
-        }
-        Set<PortNumber> portsToBeEnabled = this.srService.getEdgePorts(deviceId);
-        changePorts(deviceId, portsToBeEnabled, enabled);
-        return portsToBeEnabled;
-    }
-
-    private void changePorts(DeviceId deviceId, Set<PortNumber> portNumbers, boolean enabled) {
-        log.info("{} {} on {}", enabled ? "Enabled" : "Disabled", portNumbers, deviceId);
-        portNumbers.forEach(portNumber ->
-            deviceAdminService.changePortState(deviceId, portNumber, enabled));
-    }
-
-    private class PortChecker implements Runnable {
-        int retries;
-        DeviceId deviceId;
-
-        PortChecker(DeviceId deviceId, int retries) {
-            this.deviceId = deviceId;
-            this.retries = retries;
-        }
-
-        @Override
-        public void run() {
-            retries -= 1;
-            if (retries < 0) {
-                log.warn("PORT_STATS timeout. Unable to initialize {}", deviceId);
-                return;
-            }
-
-            if (!deviceAdminService.getPorts(deviceId).isEmpty()) {
-                log.info("{} reported PORT_STATS", deviceId);
-                setPhase(deviceId, Phase.PAIR);
-            }
-            log.info("{} still waiting for PORT_STATS", deviceId);
-            executor.schedule(this, PORT_CHECKER_INTERVAL, TimeUnit.SECONDS);
-        }
-    }
-
-    private class RoutingStabilityChecker implements Runnable {
-        private final CompletableFuture<Void> future;
-
-        RoutingStabilityChecker(CompletableFuture<Void> future) {
-            this.future = future;
-        }
-
-        @Override
-        public void run() {
-            // Do not continue if the future has been completed
-            if (future.isDone()) {
-                log.trace("RouteStabilityChecker is done. Stop checking");
-                return;
-            }
-
-            if (srService.isRoutingStable()) {
-                log.trace("Routing is stable");
-                future.complete(null);
-            } else {
-                log.trace("Routing is not yet stable");
-                executor.schedule(this, ROUTING_CHECKER_DELAY, TimeUnit.SECONDS);
-            }
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/package-info.java
deleted file mode 100644
index 3788085..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Phased recovery implementation.
- */
-package org.onosproject.segmentrouting.phasedrecovery.impl;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java
deleted file mode 100644
index 417a795..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-
-import com.google.common.base.MoreObjects;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.Link;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Implementation of the default l2 tunnel.
- */
-public class DefaultL2Tunnel implements L2Tunnel {
-
-    /**
-     * Mode of the pseudo wire.
-     */
-    private L2Mode pwMode;
-    /**
-     * Service delimiting tag.
-     */
-    private VlanId sdTag;
-    /**
-     * Tunnel id.
-     */
-    private long tunnelId;
-    /**
-     * Pseudo wire label.
-     */
-    private MplsLabel pwLabel;
-    /**
-     * Inter-CO label.
-     */
-    private MplsLabel interCoLabel;
-
-    private List<Link> pathUsed;
-
-    /**
-     * Vlan which will be used for the encapsualted
-     * vlan traffic.
-     */
-    private VlanId transportVlan;
-
-    /**
-     * Creates a inter-co l2 tunnel using the
-     * supplied parameters.
-     *
-     * @param mode         the tunnel mode
-     * @param sdtag        the service delimiting tag
-     * @param tunnelId     the tunnel id
-     * @param pwLabel      the pseudo wire label
-     * @param interCoLabel the inter central office label
-     */
-    public DefaultL2Tunnel(L2Mode mode, VlanId sdtag, long tunnelId, MplsLabel pwLabel, MplsLabel interCoLabel) {
-        checkNotNull(mode);
-        checkArgument(tunnelId > 0);
-        checkNotNull(pwLabel);
-        checkNotNull(interCoLabel);
-
-        this.pwMode = mode;
-        this.sdTag = sdtag;
-        this.tunnelId = tunnelId;
-        this.pwLabel = pwLabel;
-        this.interCoLabel = interCoLabel;
-    }
-
-    /**
-     * Creates a l2Tunnel from a given tunnel.
-     *
-     * @param l2Tunnel to replicate
-     */
-    public DefaultL2Tunnel(DefaultL2Tunnel l2Tunnel) {
-
-        this.pwMode = l2Tunnel.pwMode();
-        this.sdTag = l2Tunnel.sdTag();
-        this.tunnelId = l2Tunnel.tunnelId();
-        this.pwLabel = l2Tunnel.pwLabel();
-        this.interCoLabel = l2Tunnel.interCoLabel();
-        this.pathUsed = l2Tunnel.pathUsed();
-        this.transportVlan = l2Tunnel.transportVlan;
-    }
-
-    /**
-     * Creates a intra-co l2 tunnel using the
-     * supplied parameters.
-     *
-     * @param mode     the tunnel mode
-     * @param sdtag    the service delimiting tag
-     * @param tunnelId the tunnel id
-     * @param pwLabel  the pseudo wire label
-     */
-    public DefaultL2Tunnel(L2Mode mode, VlanId sdtag, long tunnelId, MplsLabel pwLabel) {
-        this(mode, sdtag, tunnelId, pwLabel, MplsLabel.mplsLabel(MplsLabel.MAX_MPLS));
-    }
-
-
-    /**
-     * Creates an empty l2 tunnel.
-     **/
-    public DefaultL2Tunnel() {
-        this.pwMode = null;
-        this.sdTag = null;
-        this.tunnelId = 0;
-        this.pwLabel = null;
-        this.interCoLabel = null;
-    }
-
-    /**
-     * Returns the mode of the pseudo wire.
-     *
-     * @return the pseudo wire mode
-     */
-    @Override
-    public L2Mode pwMode() {
-        return pwMode;
-    }
-
-    /**
-     * Returns the service delimitation
-     * tag.
-     *
-     * @return the service delimitation vlan id
-     */
-    @Override
-    public VlanId sdTag() {
-        return sdTag;
-    }
-
-    /**
-     * Returns the tunnel id of the pseudo wire.
-     *
-     * @return the pseudo wire tunnel id
-     */
-    @Override
-    public long tunnelId() {
-        return tunnelId;
-    }
-
-    /**
-     * Returns the pw label.
-     *
-     * @return the mpls pw label
-     */
-    @Override
-    public MplsLabel pwLabel() {
-        return pwLabel;
-    }
-
-    /**
-     * Set the path for the pseudowire.
-     *
-     * @param path The path to set
-     */
-    @Override
-    public void setPath(List<Link> path) {
-        pathUsed = new ArrayList<>(path);
-    }
-
-    /**
-     * Set the transport vlan for the pseudowire.
-     *
-     * @param vlan the vlan to use.
-     */
-    @Override
-    public void setTransportVlan(VlanId vlan) {
-        transportVlan = vlan;
-    }
-
-    /**
-     * Returns the used path of the pseudowire.
-     *
-     * @return pathUsed
-     */
-    @Override
-    public List<Link> pathUsed() {
-        return pathUsed;
-    }
-
-    @Override
-    public VlanId transportVlan() {
-        return transportVlan;
-    }
-
-
-    /**
-     * Returns the inter-co label.
-     *
-     * @return the mpls inter-co label
-     */
-    @Override
-    public MplsLabel interCoLabel() {
-        return interCoLabel;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(this.tunnelId, this.pwMode, this.sdTag, this.pwLabel, this.interCoLabel);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (o instanceof DefaultL2Tunnel) {
-            DefaultL2Tunnel that = (DefaultL2Tunnel) o;
-            return this.tunnelId == that.tunnelId &&
-                    this.pwMode.equals(that.pwMode) &&
-                    this.sdTag.equals(that.sdTag) &&
-                    this.pwLabel.equals(that.pwLabel) &&
-                    this.interCoLabel.equals(that.interCoLabel);
-        }
-
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("pwMode", pwMode())
-                .add("sdTag", sdTag())
-                .add("tunnelId", tunnelId())
-                .add("pwLabel", pwLabel())
-                .add("interCoLabel", interCoLabel())
-                .add("transportVlan", transportVlan())
-                .toString();
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java
deleted file mode 100644
index 7a47972..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-import com.google.common.base.MoreObjects;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Helper class to carry the l2 tunnel
- * and its policy.
- */
-public class DefaultL2TunnelDescription implements L2TunnelDescription {
-
-    /**
-     * The l2 tunnel.
-     */
-    private L2Tunnel l2Tunnel;
-
-    /**
-     * The l2 tunnel policy.
-     */
-    private L2TunnelPolicy l2TunnelPolicy;
-
-    /**
-     * Creates a l2 tunnel description using the given info.
-     *
-     * @param l2Tunnel the l2 tunnel
-     * @param l2TunnelPolicy the l2 tunnel description
-     */
-    public DefaultL2TunnelDescription(L2Tunnel l2Tunnel,
-                                      L2TunnelPolicy l2TunnelPolicy) {
-        checkNotNull(l2Tunnel);
-        checkNotNull(l2TunnelPolicy);
-
-        this.l2Tunnel = l2Tunnel;
-        this.l2TunnelPolicy = l2TunnelPolicy;
-    }
-
-    /**
-     * Creates an empty l2 tunnel description.
-     */
-    public DefaultL2TunnelDescription() {
-        this.l2Tunnel = null;
-        this.l2TunnelPolicy = null;
-    }
-
-    @Override
-    public L2Tunnel l2Tunnel() {
-        return l2Tunnel;
-    }
-
-    @Override
-    public L2TunnelPolicy l2TunnelPolicy() {
-        return l2TunnelPolicy;
-    }
-
-    @Override
-    public void setL2Tunnel(L2Tunnel tunnel) {
-        l2Tunnel = tunnel;
-    }
-
-    @Override
-    public void setL2TunnelPolicy(L2TunnelPolicy policy) {
-        l2TunnelPolicy = policy;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(this.l2Tunnel, this.l2TunnelPolicy);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (o instanceof DefaultL2TunnelDescription) {
-            DefaultL2TunnelDescription that = (DefaultL2TunnelDescription) o;
-            // Equality is based on tunnel id and pw label
-            // which is always the last label.
-            return this.l2Tunnel.equals(that.l2Tunnel) &&
-                    this.l2TunnelPolicy.equals(that.l2TunnelPolicy);
-        }
-
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("l2Tunnel", l2Tunnel())
-                .add("l2TunnelPolicy", l2TunnelPolicy())
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
deleted file mode 100644
index 99ff091..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
+++ /dev/null
@@ -1,1490 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import org.apache.commons.lang3.RandomUtils;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.topology.LinkWeigher;
-import org.onosproject.segmentrouting.SRLinkWeigher;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.DistributedLock;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.StorageException;
-import org.onosproject.store.service.Versioned;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
-
-import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.INITIATION;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.TERMINATION;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result.*;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.FWD;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.REV;
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
-
-/**
- * Handler for pseudowire management.
- */
-public class DefaultL2TunnelHandler implements L2TunnelHandler {
-
-    private static final String LOCK_NAME = "l2-tunnel-handler-lock";
-    private static final Logger log = LoggerFactory.getLogger(DefaultL2TunnelHandler.class);
-
-    private final SegmentRoutingManager srManager;
-    /**
-     * To store the next objectives related to the initiation.
-     */
-    private final ConsistentMap<String, NextObjective> l2InitiationNextObjStore;
-    /**
-     * To store the next objectives related to the termination.
-     */
-    private final ConsistentMap<String, NextObjective> l2TerminationNextObjStore;
-
-    /**
-     * To store policies.
-     */
-    private final ConsistentMap<String, L2TunnelPolicy> l2PolicyStore;
-
-    /**
-     * To store tunnels.
-     */
-    private final ConsistentMap<String, L2Tunnel> l2TunnelStore;
-
-    /**
-     * To store pending tunnels that need to be installed.
-     */
-    private final ConsistentMap<String, L2Tunnel> pendingL2TunnelStore;
-
-    /**
-     * To store pending policies that need to be installed.
-     */
-    private final ConsistentMap<String, L2TunnelPolicy> pendingL2PolicyStore;
-
-    private final KryoNamespace.Builder l2TunnelKryo;
-
-    /**
-     * Lock used when creating or removing pseudowires.
-     */
-    private final DistributedLock pwLock;
-
-    private static final long LOCK_TIMEOUT = 2000;
-
-    /**
-     * Create a l2 tunnel handler for the deploy and
-     * for the tear down of pseudo wires.
-     *
-     * @param segmentRoutingManager the segment routing manager
-     */
-    public DefaultL2TunnelHandler(SegmentRoutingManager segmentRoutingManager) {
-        srManager = segmentRoutingManager;
-        l2TunnelKryo = new KryoNamespace.Builder()
-                .register(KryoNamespaces.API)
-                .register(L2Tunnel.class,
-                          L2TunnelPolicy.class,
-                          DefaultL2Tunnel.class,
-                          DefaultL2TunnelPolicy.class,
-                          L2Mode.class,
-                          MplsLabel.class,
-                          VlanId.class,
-                          ConnectPoint.class);
-
-        l2InitiationNextObjStore = srManager.
-                storageService.
-                <String, NextObjective>consistentMapBuilder().
-                withName("onos-l2initiation-nextobj-store").
-                withSerializer(Serializer.using(l2TunnelKryo.build())).
-                build();
-
-        l2TerminationNextObjStore = srManager.storageService.
-                <String, NextObjective>consistentMapBuilder()
-                .withName("onos-l2termination-nextobj-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        l2PolicyStore = srManager.storageService
-                .<String, L2TunnelPolicy>consistentMapBuilder()
-                .withName("onos-l2-policy-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        l2TunnelStore = srManager.storageService
-                .<String, L2Tunnel>consistentMapBuilder()
-                .withName("onos-l2-tunnel-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        pendingL2PolicyStore = srManager.storageService
-                .<String, L2TunnelPolicy>consistentMapBuilder()
-                .withName("onos-l2-pending-policy-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        pendingL2TunnelStore = srManager.storageService
-                .<String, L2Tunnel>consistentMapBuilder()
-                .withName("onos-l2-pending-tunnel-store")
-                .withSerializer(Serializer.using(l2TunnelKryo.build()))
-                .build();
-
-        pwLock = srManager.storageService.lockBuilder()
-                .withName(LOCK_NAME)
-                .build()
-                .asLock(LOCK_TIMEOUT);
-    }
-
-    /**
-     * Used by manager only in initialization.
-     */
-    @Override
-    public void init() {
-        // Since we have no pseudowires in netcfg there
-        // is nothing to do in initialization.
-        // I leave it here because potentially we might need to
-        // use it in the future.
-    }
-
-    @Override
-    public Set<L2TunnelDescription> getL2Descriptions(boolean pending) {
-            // get pending tunnels/policies OR installed tunnels/policies
-            List<L2Tunnel> tunnels = pending ? getL2PendingTunnels() : getL2Tunnels();
-            List<L2TunnelPolicy> policies = pending ? getL2PendingPolicies() : getL2Policies();
-            return tunnels.stream()
-                .map(l2Tunnel -> {
-                    L2TunnelPolicy policy = null;
-                    for (L2TunnelPolicy l2Policy : policies) {
-                        if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
-                            policy = l2Policy;
-                            break;
-                        }
-                    }
-
-                    return new DefaultL2TunnelDescription(l2Tunnel, policy);
-                })
-                .collect(Collectors.toSet());
-    }
-
-    @Override
-    public List<L2TunnelPolicy> getL2Policies() {
-        return new ArrayList<>(l2PolicyStore
-                .values()
-                .stream()
-                .map(Versioned::value)
-                .collect(Collectors.toList()));
-    }
-
-    @Override
-    public List<L2Tunnel> getL2Tunnels() {
-        return new ArrayList<>(l2TunnelStore
-                .values()
-                .stream()
-                .map(Versioned::value)
-                .collect(Collectors.toList()));
-    }
-
-    @Override
-    public List<L2TunnelPolicy> getL2PendingPolicies() {
-        return new ArrayList<>(pendingL2PolicyStore
-                                       .values()
-                                       .stream()
-                                       .map(Versioned::value)
-                                       .collect(Collectors.toList()));
-    }
-
-    @Override
-    public List<L2Tunnel> getL2PendingTunnels() {
-        return new ArrayList<>(pendingL2TunnelStore
-                                       .values()
-                                       .stream()
-                                       .map(Versioned::value)
-                                       .collect(Collectors.toList()));
-    }
-
-    @Override
-    public Result verifyGlobalValidity(L2TunnelDescription pwToAdd) {
-
-        // get both added and pending pseudowires
-        List<L2TunnelDescription> newPseudowires = new ArrayList<>();
-        newPseudowires.addAll(getL2Descriptions(false));
-        newPseudowires.addAll(getL2Descriptions(true));
-        // add the new one
-        newPseudowires.add(pwToAdd);
-
-        return configurationValidity(newPseudowires);
-    }
-
-    @Override
-    public ImmutableMap<String, NextObjective> getInitNext() {
-        if (l2InitiationNextObjStore != null) {
-            return ImmutableMap.copyOf(l2InitiationNextObjStore.asJavaMap());
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public ImmutableMap<String, NextObjective> getTermNext() {
-        if (l2TerminationNextObjStore != null) {
-            return ImmutableMap.copyOf(l2TerminationNextObjStore.asJavaMap());
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public void removeNextId(int nextId) {
-        l2InitiationNextObjStore.entrySet().forEach(e -> {
-            if (e.getValue().value().id() == nextId) {
-                l2InitiationNextObjStore.remove(e.getKey());
-            }
-        });
-
-        l2TerminationNextObjStore.entrySet().forEach(e -> {
-            if (e.getValue().value().id() == nextId) {
-                l2TerminationNextObjStore.remove(e.getKey());
-            }
-        });
-    }
-
-    /**
-     * Returns the new vlan id for an ingress point of a
-     * pseudowire. For double tagged, it is the outer,
-     * For single tagged it is the single tag, and for
-     * inner it is None.
-     *
-     * @param ingressOuter vlanid of ingress outer
-     * @param ingressInner vlanid of ingress inner
-     * @param egressOuter  vlanid of egress outer
-     * @param egressInner  vlanid of egress inner
-     * @return returns the vlan id which will be installed at vlan table 1.
-     */
-    private VlanId determineEgressVlan(VlanId ingressOuter, VlanId ingressInner,
-                                      VlanId egressOuter, VlanId egressInner) {
-        // validity of vlan combinations was checked at verifyPseudowire
-        if (!(ingressOuter.equals(VlanId.NONE))) {
-            return egressOuter;
-        } else if (!(ingressInner.equals(VlanId.NONE))) {
-            return egressInner;
-        } else {
-            return VlanId.vlanId("None");
-        }
-    }
-
-    /**
-     * Returns the devices existing on a given path.
-     *
-     * @param path The path to traverse.
-     * @return The devices on the path with the order they
-     *         are traversed.
-     */
-    private List<DeviceId> getDevicesOnPath(List<Link> path) {
-
-        // iterate over links and get all devices in the order
-        // we find them
-        List<DeviceId> deviceList = new ArrayList<>();
-        for (Link link : path) {
-            if (!deviceList.contains(link.src().deviceId())) {
-                deviceList.add(link.src().deviceId());
-            }
-            if (!deviceList.contains(link.dst().deviceId())) {
-                deviceList.add(link.dst().deviceId());
-            }
-        }
-
-        return deviceList;
-    }
-
-    /**
-     * Returns true if path is valid according to the current logic.
-     * For example : leaf to spine pseudowires can be either leaf-spine or
-     * leaf-spine-spine. However, in the configuration we might specify spine device
-     * first which will result in spine-spine-leaf. If leafSpinePw == true we have one of these
-     * two cases and need to provision for them.
-     *
-     * If we have a leaf to leaf pseudowire then all the intermediate devices must
-     * be spines. However, in case of paired switches we can have two leafs interconnected
-     * with each other directly.
-     *
-     * @param path the chosen path
-     * @param leafSpinePw if it is a leaf to spine pseudowire
-     * @return True if path size is valid, false otherwise.
-     */
-    private boolean isValidPath(List<Link> path, boolean leafSpinePw) {
-
-        log.debug("Checking path validity for pseudowire.");
-        List<DeviceId> devices = getDevicesOnPath(path);
-        if (devices.size() < 2) {
-            log.error("Path size for pseudowire should be greater than 1!");
-            return false;
-        }
-
-        try {
-            if (leafSpinePw) {
-                // can either be leaf-spine-spine or leaf-spine
-                // first device is leaf, all other must be spines
-                log.debug("Devices on path are {} for leaf to spine pseudowire", devices);
-                // if first device is a leaf then all other must be spines
-                if (srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
-                    devices.remove(0);
-                    for (DeviceId devId : devices) {
-                        log.debug("Device {} should be a spine!", devId);
-                        if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
-                            return false;
-                        }
-                    }
-                } else {
-                    // if first device is spine, last device must be a leaf
-                    // all other devices must be spines
-                    if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
-                        return false;
-                    }
-                    devices.remove(devices.size() - 1);
-                    for (DeviceId devId : devices) {
-                        log.debug("Device {} should be a spine!", devId);
-                        if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
-                            return false;
-                        }
-                    }
-                }
-            } else {
-                // can either be leaf-leaf (paired leafs) / leaf-spine-leaf
-                // or leaf-spine-spine-leaf
-                log.debug("Devices on path are {} for leaf to leaf pseudowire", devices);
-                // check first device, needs to be a leaf
-                if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
-                    return false;
-                }
-                // check last device, needs to be a leaf
-                if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
-                    return false;
-                }
-                // remove these devices, rest must all be spines
-                devices.remove(0);
-                devices.remove(devices.size() - 1);
-                for (DeviceId devId : devices) {
-                    log.debug("Device {} should be a spine!", devId);
-                    if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
-                        return false;
-                    }
-                }
-
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            log.error("Device not found in configuration : {}", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Adds a single pseudowire.
-     *
-     * @param pw The pseudowire to deploy
-     * @return result of pseudowire deployment
-     */
-    public Result deployPseudowire(L2TunnelDescription pw) {
-
-        try {
-            // take the lock
-            pwLock.lock();
-            Result result;
-            long l2TunnelId;
-            log.debug("Pseudowire with {} deployment started, check log for any errors in this process!",
-                      pw.l2Tunnel().tunnelId());
-            l2TunnelId = pw.l2Tunnel().tunnelId();
-            // The tunnel id cannot be 0.
-            if (l2TunnelId == 0) {
-                log.warn("Tunnel id id must be > 0 in {}", l2TunnelId);
-                return Result.WRONG_PARAMETERS
-                        .appendError("Tunnel id id must be > 0");
-            }
-
-            result = verifyGlobalValidity(pw);
-            if (result != SUCCESS) {
-                log.error("Global validity for pseudowire {} is wrong!", l2TunnelId);
-                return result;
-            }
-
-            // leafSpinePw determines if this is a leaf-leaf
-            // or leaf-spine pseudowire
-            boolean leafSpinePw;
-            ConnectPoint cp1 = pw.l2TunnelPolicy().cP1();
-            ConnectPoint cp2 = pw.l2TunnelPolicy().cP2();
-            try {
-                // differentiate between leaf-leaf pseudowires and leaf-spine
-                if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
-                        !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
-                    log.error("Can not deploy pseudowire {} from spine to spine!", l2TunnelId);
-                    return Result.WRONG_PARAMETERS
-                            .appendError("Can not deploy pseudowire from spine to spine!");
-                } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
-                        srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
-                    leafSpinePw = false;
-                } else {
-                    leafSpinePw = true;
-                }
-            } catch (DeviceConfigNotFoundException e) {
-                log.error("Device for pseudowire {} connection points does not exist in the configuration", l2TunnelId);
-                return Result.INTERNAL_ERROR
-                        .appendError("Device for pseudowire connection points does not exist in the configuration");
-            }
-
-            // reverse the policy in order for leaf switch to be at CP1
-            // this will help us for re-using SRLinkWeigher for computing valid paths
-            L2TunnelPolicy reversedPolicy = reverseL2TunnelPolicy(pw.l2TunnelPolicy());
-            if (reversedPolicy == null) {
-                log.error("Error in reversing policy, device configuration was not found for pseudowire {}.",
-                          l2TunnelId);
-                return INTERNAL_ERROR
-                        .appendError("Device configuration not found when reversing the policy.");
-            }
-            pw.setL2TunnelPolicy(reversedPolicy);
-
-            // get path here, need to use the same for fwd and rev direction
-            List<Link> path = getPath(pw.l2TunnelPolicy().cP1(),
-                                      pw.l2TunnelPolicy().cP2());
-            if (path == null || path.isEmpty()) {
-                log.error("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
-                return PATH_NOT_FOUND.appendError("No path between the connection points for pseudowire!");
-            }
-
-            Link fwdNextHop;
-            Link revNextHop;
-            if (!isValidPath(path, leafSpinePw)) {
-                log.error("Deploying process : Path for pseudowire {} is not valid", l2TunnelId);
-                return INTERNAL_ERROR.appendError("Internal error : path for pseudowire is not valid!");
-            }
-            // oneHope flag is used to determine if we need to
-            // install transit mpls rules
-            boolean oneHop = true;
-            if (path.size() > 1) {
-                oneHop = false;
-            }
-
-            fwdNextHop = path.get(0);
-            revNextHop = reverseLink(path.get(path.size() - 1));
-
-            pw.l2Tunnel().setPath(path);
-            pw.l2Tunnel().setTransportVlan(srManager.getPwTransportVlan());
-
-            // next hops for next objectives
-            log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
-
-            VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
-                                                    pw.l2TunnelPolicy().cP1InnerTag(),
-                                                    pw.l2TunnelPolicy().cP2OuterTag(),
-                                                    pw.l2TunnelPolicy().cP2InnerTag());
-            result = deployPseudoWireInit(pw.l2Tunnel(),
-                                          pw.l2TunnelPolicy().cP1(),
-                                          pw.l2TunnelPolicy().cP2(),
-                                          FWD,
-                                          fwdNextHop,
-                                          oneHop,
-                                          egressVlan);
-            if (result != SUCCESS) {
-                log.error("Deploying process : Error in deploying pseudowire {} initiation for CP1", l2TunnelId);
-                return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire initiation for CP1");
-            }
-
-            result = deployPolicy(l2TunnelId,
-                                  pw.l2TunnelPolicy().cP1(),
-                                  pw.l2TunnelPolicy().cP1InnerTag(),
-                                  pw.l2TunnelPolicy().cP1OuterTag(),
-                                  egressVlan,
-                                  result.getNextId());
-            if (result != SUCCESS) {
-                log.error("Deploying process : Error in deploying pseudowire {} policy for CP1", l2TunnelId);
-                return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire policy for CP1");
-            }
-
-            result = deployPseudoWireTerm(pw.l2Tunnel(),
-                                          pw.l2TunnelPolicy().cP2(),
-                                          egressVlan,
-                                          FWD,
-                                          oneHop);
-
-            if (result != SUCCESS) {
-                log.error("Deploying process : Error in deploying pseudowire {} termination for CP1", l2TunnelId);
-                return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP1");
-            }
-
-            // We establish the reverse tunnel.
-            log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);
-            egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
-                                             pw.l2TunnelPolicy().cP2InnerTag(),
-                                             pw.l2TunnelPolicy().cP1OuterTag(),
-                                             pw.l2TunnelPolicy().cP1InnerTag());
-
-            result = deployPseudoWireInit(pw.l2Tunnel(),
-                                          pw.l2TunnelPolicy().cP2(),
-                                          pw.l2TunnelPolicy().cP1(),
-                                          REV,
-                                          revNextHop,
-                                          oneHop,
-                                          egressVlan);
-            if (result != SUCCESS) {
-                log.error("Deploying process : Error in deploying pseudowire {} initiation for CP2", l2TunnelId);
-                return Result.INTERNAL_ERROR
-                        .appendError("Error in deploying pseudowire initiation for CP2");
-            }
-
-            result = deployPolicy(l2TunnelId,
-                                  pw.l2TunnelPolicy().cP2(),
-                                  pw.l2TunnelPolicy().cP2InnerTag(),
-                                  pw.l2TunnelPolicy().cP2OuterTag(),
-                                  egressVlan,
-                                  result.getNextId());
-            if (result != SUCCESS) {
-                log.error("Deploying process : Error in deploying policy {} for CP2", l2TunnelId);
-                return Result.INTERNAL_ERROR
-                        .appendError("Deploying process : Error in deploying policy for CP2");
-            }
-
-            result = deployPseudoWireTerm(pw.l2Tunnel(),
-                                          pw.l2TunnelPolicy().cP1(),
-                                          egressVlan,
-                                          REV,
-                                          oneHop);
-
-            if (result != SUCCESS) {
-                log.error("Deploying process : Error in deploying pseudowire {} termination for CP2", l2TunnelId);
-                return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP2");
-            }
-
-            log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);
-
-            // Populate stores as the final step of the process
-            l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
-            l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());
-
-            return Result.SUCCESS;
-        } catch (StorageException.Timeout e) {
-            log.error("Can not acquire distributed lock for pseudowire {}!", pw.l2Tunnel().tunnelId());
-            return Result.INTERNAL_ERROR.appendError("Can not acquire distributed lock!");
-        } finally {
-            // release the lock
-            pwLock.unlock();
-        }
-    }
-
-    @Override
-    public Result checkIfPwExists(long tunnelId, boolean pending) {
-
-        List<L2TunnelDescription> pseudowires = getL2Descriptions(pending)
-                .stream()
-                .filter(pw -> pw.l2Tunnel().tunnelId() == tunnelId)
-                .collect(Collectors.toList());
-
-        if (pseudowires.size() == 0) {
-            String store = ((pending) ? "pending" : "installed");
-            log.debug("Pseudowire {} does not exist in {} store", tunnelId, store);
-            return Result.WRONG_PARAMETERS.
-                    appendError("Pseudowire " + tunnelId + " does not exist in " + store);
-        } else {
-            return SUCCESS;
-        }
-    }
-
-    /**
-     * Tears down connection points of pseudowires. We can either tear down both connection points,
-     * or each one of them.
-     *
-     * @param l2TunnelId The tunnel id for this pseudowire.
-     * @param tearDownFirst Boolean, true if we want to tear down cp1
-     * @param tearDownSecond Boolean, true if we want to tear down cp2
-     * @param pending Boolean, if true remove only pseudowire from pending stores since no flows/groups
-     *                in the network, else remove flows/groups in the devices also.
-     * @return Result of tearing down the pseudowire, SUCCESS if everything was ok
-     *         a descriptive error otherwise.
-     */
-    private Result tearDownConnectionPoints(long l2TunnelId, boolean tearDownFirst,
-                                            boolean tearDownSecond, boolean pending) {
-
-        Result res;
-        CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
-
-        if (l2TunnelId == 0) {
-            log.error("Removal process : Tunnel id cannot be 0");
-            return Result.WRONG_PARAMETERS.appendError("Pseudowire id can not be 0.");
-        }
-
-        res = checkIfPwExists(l2TunnelId, pending);
-        if (res != Result.SUCCESS) {
-            return res;
-        }
-
-        // remove and get the tunnel and the policy from the appropriate store
-        // if null, return error.
-        Versioned<L2Tunnel> l2TunnelVersioned = pending ?
-                pendingL2TunnelStore.remove(Long.toString(l2TunnelId)) :
-                l2TunnelStore.remove(Long.toString(l2TunnelId));
-        Versioned<L2TunnelPolicy> l2TunnelPolicyVersioned = pending ?
-                pendingL2PolicyStore.remove(Long.toString(l2TunnelId)) :
-                l2PolicyStore.remove(Long.toString(l2TunnelId));
-        if ((l2TunnelVersioned == null) || (l2TunnelPolicyVersioned == null)) {
-            log.warn("Removal process : Policy and/or tunnel missing for tunnel id {}", l2TunnelId);
-            return Result.INTERNAL_ERROR
-                    .appendError("Policy and/or tunnel missing for pseudowire!");
-        }
-
-        L2TunnelDescription pwToRemove = new DefaultL2TunnelDescription(l2TunnelVersioned.value(),
-                                                                        l2TunnelPolicyVersioned.value());
-
-        if (pending) {
-            // no need to remove flows / groups for a pseudowire
-            // in pending state
-            return Result.SUCCESS;
-        }
-
-        // remove flows/groups involving with this pseudowire
-        if (tearDownFirst) {
-            log.info("Removal process : Tearing down forward direction of pseudowire {}", l2TunnelId);
-
-            VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP1OuterTag(),
-                                                    pwToRemove.l2TunnelPolicy().cP1InnerTag(),
-                                                    pwToRemove.l2TunnelPolicy().cP2OuterTag(),
-                                                    pwToRemove.l2TunnelPolicy().cP2InnerTag());
-            deletePolicy(l2TunnelId,
-                         pwToRemove.l2TunnelPolicy().cP1(),
-                         pwToRemove.l2TunnelPolicy().cP1InnerTag(),
-                         pwToRemove.l2TunnelPolicy().cP1OuterTag(),
-                         egressVlan,
-                         fwdInitNextFuture,
-                         FWD);
-
-            fwdInitNextFuture.thenAcceptAsync(status -> {
-                if (status == null) {
-                    // Finally we will tear down the pseudo wire.
-                    tearDownPseudoWireInit(l2TunnelId,
-                                           pwToRemove.l2TunnelPolicy().cP1(),
-                                           fwdTermNextFuture,
-                                           FWD);
-                }
-            });
-
-            fwdTermNextFuture.thenAcceptAsync(status -> {
-                if (status == null) {
-                    tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
-                                           pwToRemove.l2TunnelPolicy().cP2(),
-                                           null,
-                                           FWD);
-                }
-            });
-        }
-
-        if (tearDownSecond) {
-            log.info("Removal process : Tearing down reverse direction of pseudowire {}", l2TunnelId);
-
-            VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP2OuterTag(),
-                                             pwToRemove.l2TunnelPolicy().cP2InnerTag(),
-                                             pwToRemove.l2TunnelPolicy().cP1OuterTag(),
-                                             pwToRemove.l2TunnelPolicy().cP1InnerTag());
-
-            // We do the same operations on the reverse side.
-            deletePolicy(l2TunnelId,
-                         pwToRemove.l2TunnelPolicy().cP2(),
-                         pwToRemove.l2TunnelPolicy().cP2InnerTag(),
-                         pwToRemove.l2TunnelPolicy().cP2OuterTag(),
-                         egressVlan,
-                         revInitNextFuture,
-                         REV);
-
-            revInitNextFuture.thenAcceptAsync(status -> {
-                if (status == null) {
-                    tearDownPseudoWireInit(l2TunnelId,
-                                           pwToRemove.l2TunnelPolicy().cP2(),
-                                           revTermNextFuture,
-                                           REV);
-                }
-            });
-
-            revTermNextFuture.thenAcceptAsync(status -> {
-                if (status == null) {
-                    tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
-                                           pwToRemove.l2TunnelPolicy().cP1(),
-                                           null,
-                                           REV);
-                }
-            });
-        }
-
-        return Result.SUCCESS;
-    }
-
-    /**
-     * Helper function for removing a single pseudowire.
-     *
-     * Tries to remove pseudowire from any store it might reside (pending or installed).
-     *
-     * @param l2TunnelId the id of the pseudowire to tear down
-     * @return Returns SUCCESS if no error is obeserved or an appropriate
-     * error on a failure
-     */
-    public Result tearDownPseudowire(long l2TunnelId) {
-
-        try {
-            // take the lock
-            pwLock.lock();
-
-            if (checkIfPwExists(l2TunnelId, true) == Result.SUCCESS) {
-                return tearDownConnectionPoints(l2TunnelId, true, true, true);
-            } else if (checkIfPwExists(l2TunnelId, false) == Result.SUCCESS) {
-                return tearDownConnectionPoints(l2TunnelId, true, true, false);
-            } else {
-                return Result.WRONG_PARAMETERS.appendError("Pseudowire with "
-                                                                   + l2TunnelId
-                                                                   + " did not reside in any store!");
-            }
-        } catch (StorageException.Timeout e) {
-            log.error("Can not acquire distributed lock for pseudowire {}!", l2TunnelId);
-            return Result.INTERNAL_ERROR.appendError("Can not acquire distributed lock!");
-        } finally {
-            // release the lock
-            pwLock.unlock();
-        }
-    }
-
-    @Override
-    @Deprecated
-    public void tearDown(Set<L2TunnelDescription> pwToRemove) {
-
-        for (L2TunnelDescription currentL2Tunnel : pwToRemove) {
-
-            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
-            log.info("Removing pseudowire {}", tunnelId);
-
-            Result result = tearDownPseudowire(tunnelId);
-            if (result != Result.SUCCESS) {
-                log.error("Could not remove pseudowire {}!", tunnelId);
-            }
-        }
-    }
-
-    /**
-     * Handles the policy establishment which consists in
-     * create the filtering and forwarding objectives related
-     * to the initiation and termination.
-     *
-     * @param tunnelId     the tunnel id
-     * @param ingress      the ingress point
-     * @param ingressInner the ingress inner tag
-     * @param ingressOuter the ingress outer tag
-     * @param egressVlan   Vlan-id to set, depends on ingress vlan
-     *                     combinations. For example, if pw is double tagged
-     *                     then this is the value of the outer vlan, if single
-     *                     tagged then it is the new value of the single tag.
-     *                     Should be None for untagged traffic.
-     * @param nextId       the next objective id
-     * @return the result of the operation
-     */
-    private Result deployPolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner,
-                                VlanId ingressOuter, VlanId egressVlan, int nextId) {
-        log.debug("Starting deploying policy for pseudowire {}.", tunnelId);
-
-        List<Objective> objectives = Lists.newArrayList();
-        // We create the forwarding objective for supporting
-        // the l2 tunnel.
-        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
-        // We create and add objective context.
-        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
-                                                                log.debug("FwdObj for tunnel {} populated", tunnelId),
-                                                               (objective, error) ->
-                                                                log.warn("Failed to populate fwdObj " +
-                                                                                 "for tunnel {} : {}",
-                                                                         tunnelId, error));
-        objectives.add(fwdBuilder.add(context));
-
-        // We create the filtering objective to define the
-        // permit traffic in the switch
-        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
-
-        // We add the metadata.
-        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
-                .builder()
-                .setTunnelId(tunnelId)
-                .setVlanId(egressVlan);
-        filtBuilder.withMeta(treatment.build());
-
-        // We create and add objective context.
-        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for tunnel {} populated", tunnelId),
-                                              (objective, error) -> log.warn("Failed to populate filterObj for " +
-                                                                                     "tunnel {} : {}",
-                                                                             tunnelId, error));
-        objectives.add(filtBuilder.add(context));
-
-        for (Objective objective : objectives) {
-            if (objective instanceof ForwardingObjective) {
-                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
-                log.debug("Creating new FwdObj for initiation NextObj with id={} for tunnel {}", nextId, tunnelId);
-            } else {
-                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
-                log.debug("Creating new FiltObj for tunnel {}", tunnelId);
-            }
-        }
-        return SUCCESS;
-    }
-
-    /**
-     * Handles the tunnel establishment which consists in
-     * create the next objectives related to the initiation.
-     *
-     * @param l2Tunnel  the tunnel to deploy
-     * @param ingress   the ingress connect point
-     * @param egress    the egress connect point
-     * @param direction the direction of the pw
-     * @param nextHop next hop of the initiation point
-     * @param oneHop if this pseudowire has only one link
-     * @param termVlanId the termination vlan id
-     * @return the result of the operation
-     */
-    private Result deployPseudoWireInit(L2Tunnel l2Tunnel, ConnectPoint ingress,
-                                        ConnectPoint egress, Direction direction,
-                                        Link nextHop, boolean oneHop, VlanId termVlanId) {
-        log.debug("Started deploying init next objectives for pseudowire {} for tunnel {} -> {}.",
-                  l2Tunnel.tunnelId(), ingress, egress);
-        if (nextHop == null) {
-            log.warn("No path between ingress and egress connection points for tunnel {}", l2Tunnel.tunnelId());
-            return WRONG_PARAMETERS;
-        }
-
-        // We create the next objective without the metadata
-        // context and id. We check if it already exists in the
-        // store. If not we store as it is in the store.
-        NextObjective.Builder nextObjectiveBuilder = createNextObjective(INITIATION,
-                                                                         nextHop.src(),
-                                                                         nextHop.dst(),
-                                                                         l2Tunnel,
-                                                                         egress.deviceId(),
-                                                                         oneHop,
-                                                                         termVlanId);
-
-        if (nextObjectiveBuilder == null) {
-            return INTERNAL_ERROR;
-        }
-        // We set the metadata. We will use this metadata
-        // to inform the driver we are doing a l2 tunnel.
-        TrafficSelector metadata = DefaultTrafficSelector
-                .builder()
-                .matchTunnelId(l2Tunnel.tunnelId())
-                .build();
-        nextObjectiveBuilder.withMeta(metadata);
-        int nextId = srManager.flowObjectiveService.allocateNextId();
-        if (nextId < 0) {
-            log.warn("Not able to allocate a next id for initiation");
-            return INTERNAL_ERROR;
-        }
-        nextObjectiveBuilder.withId(nextId);
-        String key = generateKey(l2Tunnel.tunnelId(), direction);
-        l2InitiationNextObjStore.put(key, nextObjectiveBuilder.add());
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Initiation l2 tunnel rule for {} populated", l2Tunnel.tunnelId()),
-                (objective, error) -> {
-                    log.warn("Failed to populate Initiation l2 tunnel rule for {}: {}", l2Tunnel.tunnelId(), error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-        NextObjective nextObjective = nextObjectiveBuilder.add(context);
-        srManager.flowObjectiveService.next(ingress.deviceId(), nextObjective);
-        log.debug("Initiation next objective for {} not found. Creating new NextObj with id={}",
-                  l2Tunnel.tunnelId(), nextObjective.id());
-        Result result = SUCCESS;
-        result.setNextId(nextObjective.id());
-        return result;
-    }
-
-    /**
-     * Handles the tunnel termination, which consists in the creation
-     * of a forwarding objective and a next objective.
-     *
-     * @param l2Tunnel   the tunnel to terminate
-     * @param egress     the egress point
-     * @param egressVlan the expected vlan at egress
-     * @param direction  the direction
-     * @return the result of the operation
-     */
-    private Result deployPseudoWireTerm(L2Tunnel l2Tunnel, ConnectPoint egress,
-                                        VlanId egressVlan, Direction direction,
-                                        boolean oneHop) {
-        log.debug("Started deploying termination objectives for pseudowire {} , direction {}.",
-                  l2Tunnel.tunnelId(), direction == FWD ? "forward" : "reverse");
-
-        // We create the group relative to the termination.
-        NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
-                                                                         l2Tunnel, egress.deviceId(),
-                                                                         oneHop,
-                                                                         egressVlan);
-        if (nextObjectiveBuilder == null) {
-            return INTERNAL_ERROR;
-        }
-        TrafficSelector metadata = DefaultTrafficSelector
-                .builder()
-                .matchVlanId(egressVlan)
-                .build();
-        nextObjectiveBuilder.withMeta(metadata);
-        int nextId = srManager.flowObjectiveService.allocateNextId();
-        if (nextId < 0) {
-            log.warn("Not able to allocate a next id for initiation");
-            return INTERNAL_ERROR;
-        }
-        nextObjectiveBuilder.withId(nextId);
-        String key = generateKey(l2Tunnel.tunnelId(), direction);
-        l2TerminationNextObjStore.put(key, nextObjectiveBuilder.add());
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("Termination l2 tunnel rule for {} populated", l2Tunnel.tunnelId()),
-                (objective, error) -> {
-                    log.warn("Failed to populate termination l2 tunnel rule for {}: {}", l2Tunnel.tunnelId(), error);
-                    srManager.invalidateNextObj(objective.id());
-                });
-        NextObjective nextObjective = nextObjectiveBuilder.add(context);
-        srManager.flowObjectiveService.next(egress.deviceId(), nextObjective);
-        log.debug("Termination next objective for {} not found. Creating new NextObj with id={}",
-                  l2Tunnel.tunnelId(), nextObjective.id());
-
-        // We create the flow relative to the termination.
-        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(), l2Tunnel.tunnelId(),
-                                                                        egress.port(), nextObjective.id());
-        context = new DefaultObjectiveContext((objective) -> log.debug("FwdObj for tunnel termination {} populated",
-                                                                       l2Tunnel.tunnelId()),
-                                              (objective, error) -> log.warn("Failed to populate fwdrObj" +
-                                                                             " for tunnel termination {} : {}",
-                                                                             l2Tunnel.tunnelId(), error));
-        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.add(context));
-        log.debug("Creating new FwdObj for termination NextObj with id={} for tunnel {}",
-                  nextId, l2Tunnel.tunnelId());
-
-        return SUCCESS;
-    }
-
-
-    /**
-     * Creates the filtering objective according to a given policy.
-     *
-     * @param inPort   the in port
-     * @param innerTag the inner vlan tag
-     * @param outerTag the outer vlan tag
-     * @return the filtering objective
-     */
-    private FilteringObjective.Builder createFiltObjective(PortNumber inPort, VlanId innerTag, VlanId outerTag) {
-
-        log.debug("Creating connection point filtering objective for vlans {} / {}", outerTag, innerTag);
-        return DefaultFilteringObjective
-                .builder()
-                .withKey(Criteria.matchInPort(inPort))
-                .addCondition(Criteria.matchInnerVlanId(innerTag))
-                .addCondition(Criteria.matchVlanId(outerTag))
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                .permit()
-                .fromApp(srManager.appId());
-    }
-
-    /**
-     * Creates the forwarding objective for the termination.
-     *
-     * @param pwLabel    the pseudo wire label
-     * @param tunnelId   the tunnel id
-     * @param egressPort the egress port
-     * @param nextId     the next step
-     * @return the forwarding objective to support the termination
-     */
-    private ForwardingObjective.Builder createTermFwdObjective(MplsLabel pwLabel, long tunnelId,
-                                                               PortNumber egressPort, int nextId) {
-
-        log.debug("Creating forwarding objective for termination for tunnel {} : pwLabel {}, egressPort {}, nextId {}",
-                 tunnelId, pwLabel, egressPort, nextId);
-        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
-        TrafficTreatment.Builder trafficTreatment = DefaultTrafficTreatment.builder();
-        // The flow has to match on the pw label and bos
-        trafficSelector.matchEthType(Ethernet.MPLS_UNICAST);
-        trafficSelector.matchMplsLabel(pwLabel);
-        trafficSelector.matchMplsBos(true);
-        // The flow has to decrement ttl, restore ttl in
-        // pop mpls, set tunnel id and port.
-        trafficTreatment.decMplsTtl();
-        trafficTreatment.copyTtlIn();
-        trafficTreatment.popMpls();
-        trafficTreatment.setTunnelId(tunnelId);
-        trafficTreatment.setOutput(egressPort);
-
-        return DefaultForwardingObjective
-                .builder()
-                .fromApp(srManager.appId())
-                .makePermanent()
-                .nextStep(nextId)
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                .withSelector(trafficSelector.build())
-                .withTreatment(trafficTreatment.build())
-                .withFlag(VERSATILE);
-    }
-
-    /**
-     * Creates the forwarding objective for the initiation.
-     *
-     * @param tunnelId the tunnel id
-     * @param inPort   the input port
-     * @param nextId   the next step
-     * @return the forwarding objective to support the initiation.
-     */
-    private ForwardingObjective.Builder createInitFwdObjective(long tunnelId, PortNumber inPort, int nextId) {
-
-        log.debug("Creating forwarding objective for tunnel {} : Port {} , nextId {}", tunnelId, inPort, nextId);
-        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
-
-        // The flow has to match on the mpls logical
-        // port and the tunnel id.
-        trafficSelector.matchTunnelId(tunnelId);
-        trafficSelector.matchInPort(inPort);
-
-        return DefaultForwardingObjective
-                .builder()
-                .fromApp(srManager.appId())
-                .makePermanent()
-                .nextStep(nextId)
-                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
-                .withSelector(trafficSelector.build())
-                .withFlag(VERSATILE);
-
-    }
-
-    /**
-     * Creates the next objective according to a given
-     * pipeline. We don't set the next id and we don't
-     * create the final meta to check if we are re-using
-     * the same next objective for different tunnels.
-     *
-     * @param pipeline the pipeline to support
-     * @param srcCp    the source port
-     * @param dstCp    the destination port
-     * @param l2Tunnel the tunnel to support
-     * @param egressId the egress device id
-     * @param oneHop if the pw only has one hop, push only pw label
-     * @param termVlanId the outer vlan id of the packet exiting a termination point
-     * @return the next objective to support the pipeline
-     */
-    private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp,
-                                                      ConnectPoint dstCp,  L2Tunnel l2Tunnel,
-                                                      DeviceId egressId, boolean oneHop,
-                                                      VlanId termVlanId) {
-        log.debug("Creating {} next objective for pseudowire {}.",
-                  pipeline == TERMINATION ? "termination" : "inititation");
-
-        NextObjective.Builder nextObjBuilder;
-        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
-        if (pipeline == INITIATION) {
-            nextObjBuilder = DefaultNextObjective
-                    .builder()
-                    .withType(NextObjective.Type.SIMPLE)
-                    .fromApp(srManager.appId());
-            // The pw label is the bottom of stack. It has to
-            // be different -1.
-            if (l2Tunnel.pwLabel().toInt() == MplsLabel.MAX_MPLS) {
-                log.error("Pw label not configured");
-                return null;
-            }
-            treatmentBuilder.pushMpls();
-            treatmentBuilder.setMpls(l2Tunnel.pwLabel());
-            treatmentBuilder.setMplsBos(true);
-            treatmentBuilder.copyTtlOut();
-
-            // If the inter-co label is present we have to set the label.
-            if (l2Tunnel.interCoLabel().toInt() != MplsLabel.MAX_MPLS) {
-                treatmentBuilder.pushMpls();
-                treatmentBuilder.setMpls(l2Tunnel.interCoLabel());
-                treatmentBuilder.setMplsBos(false);
-                treatmentBuilder.copyTtlOut();
-            }
-
-            // if not oneHop install transit mpls labels also
-            if (!oneHop) {
-                // We retrieve the sr label from the config
-                // specific for pseudowire traffic
-                // using the egress leaf device id.
-                MplsLabel srLabel;
-                try {
-                    srLabel = MplsLabel.mplsLabel(srManager.deviceConfiguration().getPWRoutingLabel(egressId));
-
-                } catch (DeviceConfigNotFoundException e) {
-                    log.error("Sr label for pw traffic not configured");
-                    return null;
-                }
-
-                treatmentBuilder.pushMpls();
-                treatmentBuilder.setMpls(srLabel);
-                treatmentBuilder.setMplsBos(false);
-                treatmentBuilder.copyTtlOut();
-            }
-
-            // We have to rewrite the src and dst mac address.
-            MacAddress ingressMac;
-            try {
-                ingressMac = srManager.deviceConfiguration().getDeviceMac(srcCp.deviceId());
-            } catch (DeviceConfigNotFoundException e) {
-                log.error("Was not able to find the ingress mac");
-                return null;
-            }
-            treatmentBuilder.setEthSrc(ingressMac);
-            MacAddress neighborMac;
-            try {
-                neighborMac = srManager.deviceConfiguration().getDeviceMac(dstCp.deviceId());
-            } catch (DeviceConfigNotFoundException e) {
-                log.error("Was not able to find the neighbor mac");
-                return null;
-            }
-            treatmentBuilder.setEthDst(neighborMac);
-
-            // set the appropriate transport vlan from tunnel information
-            treatmentBuilder.setVlanId(l2Tunnel.transportVlan());
-        } else {
-            // We create the next objective which
-            // will be a simple l2 group.
-            nextObjBuilder = DefaultNextObjective
-                    .builder()
-                    .withType(NextObjective.Type.SIMPLE)
-                    .fromApp(srManager.appId());
-
-            // for termination point we use the outer vlan of the
-            // encapsulated packet for the vlan
-            treatmentBuilder.setVlanId(termVlanId);
-        }
-
-        treatmentBuilder.setOutput(srcCp.port());
-        nextObjBuilder.addTreatment(treatmentBuilder.build());
-        return nextObjBuilder;
-    }
-
-    /**
-     * Reverse an l2 tunnel policy in order to have as CP1 the leaf switch,
-     * in case one of the switches is a spine.
-     *
-     * This makes possible the usage of SRLinkWeigher for computing valid paths,
-     * which cuts leaf-spine links from the path computation with a src different
-     * than the source leaf.
-     *
-     * @param policy The policy to reverse, if needed
-     * @return a l2TunnelPolicy containing the leaf at CP1, suitable for usage with
-     *         current SRLinkWeigher
-     */
-    private L2TunnelPolicy reverseL2TunnelPolicy(L2TunnelPolicy policy) {
-
-        log.debug("Reversing policy for pseudowire.");
-        try {
-            // if cp1 is a leaf, just return
-            if (srManager.deviceConfiguration().isEdgeDevice(policy.cP1().deviceId())) {
-                return policy;
-            } else {
-                // return a policy with reversed cp1 and cp2, and also with reversed tags
-                return new DefaultL2TunnelPolicy(policy.tunnelId(),
-                                                 policy.cP2(), policy.cP2InnerTag(), policy.cP2OuterTag(),
-                                                 policy.cP1(), policy.cP1InnerTag(), policy.cP1OuterTag());
-
-            }
-        } catch (DeviceConfigNotFoundException e) {
-            // should never come here, since it has been checked before
-            log.error("Configuration for device {}, does not exist!");
-            return null;
-        }
-    }
-
-    /**
-     * Reverses a link.
-     *
-     * @param link link to be reversed
-     * @return the reversed link
-     */
-    private Link reverseLink(Link link) {
-
-        DefaultLink.Builder linkBuilder = DefaultLink.builder();
-
-        linkBuilder.src(link.dst());
-        linkBuilder.dst(link.src());
-        linkBuilder.type(link.type());
-        linkBuilder.providerId(link.providerId());
-
-        return linkBuilder.build();
-    }
-
-    /**
-     * Returns the path betwwen two connect points.
-     *
-     * @param srcCp source connect point
-     * @param dstCp destination connect point
-     * @return the path
-     */
-    private List<Link> getPath(ConnectPoint srcCp, ConnectPoint dstCp) {
-
-        // use SRLinkWeigher to avoid pair links, and also
-        // avoid going from the spine to the leaf and to the
-        // spine again, we need to have the leaf as CP1 here.
-        LinkWeigher srLw = new SRLinkWeigher(srManager, srcCp.deviceId(), new HashSet<Link>());
-
-        Set<Path> paths = srManager.topologyService.
-                getPaths(srManager.topologyService.currentTopology(),
-                srcCp.deviceId(), dstCp.deviceId(), srLw);
-
-        log.debug("Paths obtained from topology service {}", paths);
-
-        // We randomly pick a path.
-        if (paths.isEmpty()) {
-            return null;
-        }
-        int size = paths.size();
-        int index = RandomUtils.nextInt(0, size);
-
-        List<Link> result = Iterables.get(paths, index).links();
-        log.debug("Randomly picked a path {}", result);
-
-        return result;
-    }
-
-    /**
-     * Deletes a given policy using the parameter supplied.
-     *
-     * @param tunnelId     the tunnel id
-     * @param ingress      the ingress point
-     * @param ingressInner the ingress inner vlan id
-     * @param ingressOuter the ingress outer vlan id
-     * @param future       to perform the async operation
-     * @param direction    the direction: forward or reverse
-     */
-    private void deletePolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner, VlanId ingressOuter,
-                              VlanId egressVlan, CompletableFuture<ObjectiveError> future, Direction direction) {
-
-        String key = generateKey(tunnelId, direction);
-        if (!l2InitiationNextObjStore.containsKey(key)) {
-            log.error("Abort delete of policy for tunnel {}: next does not exist in the store", tunnelId);
-            if (future != null) {
-                future.complete(null);
-            }
-            return;
-        }
-        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
-        int nextId = nextObjective.id();
-        List<Objective> objectives = Lists.newArrayList();
-        // We create the forwarding objective.
-        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
-        ObjectiveContext context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous fwdObj for policy {} removed", tunnelId);
-                if (future != null) {
-                    future.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.error("Failed to remove previous fwdObj for policy {}: {}", tunnelId, error);
-                if (future != null) {
-                    future.complete(error);
-                }
-            }
-        };
-        objectives.add(fwdBuilder.remove(context));
-        // We create the filtering objective to define the
-        // permit traffic in the switch
-        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
-        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
-                .builder()
-                .setTunnelId(tunnelId)
-                .setVlanId(egressVlan);
-        filtBuilder.withMeta(treatment.build());
-        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for policy {} revoked", tunnelId),
-                                              (objective, error) ->
-                                                      log.warn("Failed to revoke filterObj for policy {}",
-                                                               tunnelId, error));
-        objectives.add(filtBuilder.remove(context));
-
-        for (Objective objective : objectives) {
-            if (objective instanceof ForwardingObjective) {
-                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
-            } else {
-                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
-            }
-        }
-    }
-
-    /**
-     * Deletes the pseudo wire initiation.
-     *
-     * @param l2TunnelId the tunnel id
-     * @param ingress    the ingress connect point
-     * @param future     to perform an async operation
-     * @param direction  the direction: reverse of forward
-     */
-    private void tearDownPseudoWireInit(long l2TunnelId, ConnectPoint ingress,
-                                        CompletableFuture<ObjectiveError> future, Direction direction) {
-        log.debug("Starting tearing dowing initation of pseudowire {} for direction {}.",
-                  l2TunnelId, direction == FWD ? "forward" : "reverse");
-        String key = generateKey(l2TunnelId, direction);
-        if (!l2InitiationNextObjStore.containsKey(key)) {
-            log.error("Abort delete of {} for {}: next does not exist in the store", INITIATION, key);
-            if (future != null) {
-                future.complete(null);
-            }
-            return;
-        }
-
-        // un-comment in case you want to delete groups used by the pw
-        // however, this will break the update of pseudowires cause the L2 interface group can
-        // not be deleted (it is referenced by other groups)
-        /*
-        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
-        ObjectiveContext context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous {} next for {} removed", INITIATION, key);
-                if (future != null) {
-                    future.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.warn("Failed to remove previous {} next for {}: {}", INITIATION, key, error);
-                if (future != null) {
-                    future.complete(error);
-                }
-            }
-        };
-        srManager.flowObjectiveService.next(ingress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
-        */
-
-        future.complete(null);
-        l2InitiationNextObjStore.remove(key);
-    }
-
-    /**
-     * Deletes the pseudo wire termination.
-     *
-     * @param l2Tunnel  the tunnel
-     * @param egress    the egress connect point
-     * @param future    the async task
-     * @param direction the direction of the tunnel
-     */
-    private void tearDownPseudoWireTerm(L2Tunnel l2Tunnel,
-                                        ConnectPoint egress,
-                                        CompletableFuture<ObjectiveError> future,
-                                        Direction direction) {
-        log.debug("Starting tearing down termination for pseudowire {} direction {}.",
-                  l2Tunnel.tunnelId(), direction == FWD ? "forward" : "reverse");
-        String key = generateKey(l2Tunnel.tunnelId(), direction);
-        if (!l2TerminationNextObjStore.containsKey(key)) {
-            log.error("Abort delete of {} for {}: next does not exist in the store", TERMINATION, key);
-            if (future != null) {
-                future.complete(null);
-            }
-            return;
-        }
-        NextObjective nextObjective = l2TerminationNextObjStore.get(key).value();
-        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(),
-                                                                        l2Tunnel.tunnelId(),
-                                                                        egress.port(),
-                                                                        nextObjective.id());
-        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
-                                                                       log.debug("FwdObj for {} {}, " +
-                                                                                         "direction {} removed",
-                                                                                        TERMINATION,
-                                                                                        l2Tunnel.tunnelId(),
-                                                                                        direction),
-                                                               (objective, error) ->
-                                                                       log.warn("Failed to remove fwdObj " +
-                                                                                        "for {} {}" +
-                                                                                        ", direction {}",
-                                                                                TERMINATION,
-                                                                                l2Tunnel.tunnelId(),
-                                                                                error,
-                                                                                direction));
-        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.remove(context));
-
-        // un-comment in case you want to delete groups used by the pw
-        // however, this will break the update of pseudowires cause the L2 interface group can
-        // not be deleted (it is referenced by other groups)
-        /*
-        context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous {} next for {} removed", TERMINATION, key);
-                if (future != null) {
-                    future.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.warn("Failed to remove previous {} next for {}: {}", TERMINATION, key, error);
-                if (future != null) {
-                    future.complete(error);
-                }
-            }
-        };
-        srManager.flowObjectiveService.next(egress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
-        */
-
-        l2TerminationNextObjStore.remove(key);
-        future.complete(null);
-    }
-
-    /**
-     * Utilities to generate pw key.
-     *
-     * @param tunnelId  the tunnel id
-     * @param direction the direction of the pw
-     * @return the key of the store
-     */
-    private String generateKey(long tunnelId, Direction direction) {
-        return String.format("%s-%s", tunnelId, direction);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java
deleted file mode 100644
index 4738744..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-import com.google.common.base.MoreObjects;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Implementation of the default l2 tunnel policy.
- */
-public class DefaultL2TunnelPolicy implements L2TunnelPolicy {
-
-    /**
-     * Id of the tunnel associated to this policy.
-     */
-    private long tunnelId;
-    /**
-     * First connect point.
-     */
-    private ConnectPoint cP1;
-    /**
-     * Second connect point.
-     */
-    private ConnectPoint cP2;
-    /**
-     * cP1 inner vlan tag. Used in QinQ packets.
-     */
-    private VlanId cP1InnerTag;
-    /**
-     * cP1 outer vlan tag.
-     */
-    private VlanId cP1OuterTag;
-    /**
-     * cP2 inner vlan tag. Used in QinQ packets.
-     */
-    private VlanId cP2InnerTag;
-    /**
-     * cP2 outer vlan tag.
-     */
-    private VlanId cP2OuterTag;
-
-    /**
-     * Creates a default l2 tunnel policy using
-     * the given parameters.
-     *
-     * @param tunnelId the tunnel id
-     * @param cP1 the first connect point
-     * @param cP1InnerTag the cP1 inner tag
-     * @param cP1OuterTag the cP1 outer tag
-     * @param cP2 the second connect point
-     * @param cP2InnerTag the cP2 inner tag
-     * @param cP2OuterTag the cP2 outer tag
-     */
-    public DefaultL2TunnelPolicy(long tunnelId,
-                                 ConnectPoint cP1, VlanId cP1InnerTag, VlanId cP1OuterTag,
-                                 ConnectPoint cP2, VlanId cP2InnerTag, VlanId cP2OuterTag) {
-        this.cP1 = checkNotNull(cP1);
-        this.cP2 = checkNotNull(cP2);
-        this.tunnelId = tunnelId;
-        this.cP1InnerTag = cP1InnerTag;
-        this.cP1OuterTag = cP1OuterTag;
-        this.cP2InnerTag = cP2InnerTag;
-        this.cP2OuterTag = cP2OuterTag;
-    }
-
-    /**
-     * Creates a default l2 policy given the provided policy.
-     * @param policy L2policy to replicate
-     */
-    public DefaultL2TunnelPolicy(DefaultL2TunnelPolicy policy) {
-
-        this.cP1 = policy.cP1;
-        this.cP2 = policy.cP2;
-        this.tunnelId = policy.tunnelId;
-        this.cP1InnerTag = policy.cP1InnerTag;
-        this.cP1OuterTag = policy.cP1OuterTag;
-        this.cP2InnerTag = policy.cP2InnerTag;
-        this.cP2OuterTag = policy.cP2OuterTag;
-    }
-
-    @Override
-    public ConnectPoint cP1() {
-        return cP1;
-    }
-
-    @Override
-    public ConnectPoint cP2() {
-        return cP2;
-    }
-
-    @Override
-    public VlanId cP1InnerTag() {
-        return cP1InnerTag;
-    }
-
-    @Override
-    public VlanId cP1OuterTag() {
-        return cP1OuterTag;
-    }
-
-    @Override
-    public VlanId cP2InnerTag() {
-        return cP2InnerTag;
-    }
-
-    @Override
-    public VlanId cP2OuterTag() {
-        return cP2OuterTag;
-    }
-
-    @Override
-    public long tunnelId() {
-        return this.tunnelId;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(tunnelId,
-                            cP1,
-                            cP2,
-                            cP1InnerTag,
-                            cP1OuterTag,
-                            cP2InnerTag,
-                            cP2OuterTag
-        );
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (o instanceof DefaultL2TunnelPolicy) {
-            DefaultL2TunnelPolicy that = (DefaultL2TunnelPolicy) o;
-            if (this.tunnelId == that.tunnelId &&
-                    this.cP1.equals(that.cP1) &&
-                    this.cP2.equals(that.cP2) &&
-                    this.cP1InnerTag.equals(that.cP1InnerTag) &&
-                    this.cP1OuterTag.equals(that.cP1OuterTag) &&
-                    this.cP2InnerTag.equals(that.cP2InnerTag) &&
-                    this.cP2OuterTag.equals(that.cP2OuterTag)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("tunnelId", tunnelId())
-                .add("cP1", cP1())
-                .add("cP2", cP2())
-                .add("cP1InnerTag", cP1InnerTag())
-                .add("cP1OuterTag", cP1OuterTag())
-                .add("cP2InnerTag", cP2InnerTag())
-                .add("cP2OuterTag", cP2OuterTag())
-                .toString();
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Mode.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Mode.java
deleted file mode 100644
index 685a606..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Mode.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-/**
- * Enum to identify mode of the pwaas.
- */
-public enum L2Mode {
-    /**
-     * Raw mode.
-     */
-    RAW,
-    /**
-     * Tagged mode. In this case the packet need
-     * the sd tag.
-     */
-    TAGGED
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java
deleted file mode 100644
index 3e98480..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.Link;
-
-import java.util.List;
-
-public interface L2Tunnel {
-
-    /**
-     * Return the mode of the l2 tunnel.
-     *
-     * @return The pw mode.
-     */
-    L2Mode pwMode();
-
-    /**
-     * Returns the service delimiting tag.
-     *
-     * @return the sd tag
-     */
-    VlanId sdTag();
-
-    /**
-     * Returns the id of the tunnel.
-     *
-     * @return the tunnel id
-     */
-    long tunnelId();
-
-    /**
-     * Return the label of the pseudowire.
-     *
-     * @return the pw label.
-     */
-    MplsLabel pwLabel();
-
-    /**
-     * Returns the path used by the pseudowire.
-     *
-     * @return The path that is used
-     */
-    List<Link> pathUsed();
-
-    /**
-     * Returns the transport vlan used by the pseudowire.
-     *
-     * @return The transport vlan
-     */
-    VlanId transportVlan();
-
-    /**
-     * Returns the inter-co label used by the pseudowire.
-     *
-     * @return The inter CO label.
-     */
-    MplsLabel interCoLabel();
-
-    /**
-     * Sets the path that this pw uses.
-     *
-     * @param path The apth to use
-     */
-    void setPath(List<Link> path);
-
-    /**
-     * Set the transport vlan that this pw will use.
-     *
-     * @param vlan The vlan to use.
-     */
-    void setTransportVlan(VlanId vlan);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java
deleted file mode 100644
index 7be187a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-public interface L2TunnelDescription {
-
-    /**
-     * Returns the l2 tunnel.
-     *
-     * @return the l2 tunnel
-     */
-    L2Tunnel l2Tunnel();
-
-    /**
-     * Returns the l2 tunnel policy.
-     *
-     * @return the l2 tunnel policy.
-     */
-    L2TunnelPolicy l2TunnelPolicy();
-
-    /**
-     * Sets the l2 tunnel.
-     *
-     * @param tunnel the l2 tunnel to set.
-     */
-    void setL2Tunnel(L2Tunnel tunnel);
-
-    /**
-     * Sets the l2 policy.
-     *
-     * @param policy the policy to set.
-     */
-    void setL2TunnelPolicy(L2TunnelPolicy policy);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
deleted file mode 100644
index 2a003b3..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.flowobjective.NextObjective;
-
-import java.util.List;
-import java.util.Set;
-
-public interface L2TunnelHandler {
-    void init();
-
-    /**
-     * Combines policies and tunnels to create descriptions.
-     *
-     * @param pending if it is true return pending to be installed pseudowires
-     *                from the appropriate store, else return installed pseudowires
-     * @return Set of l2 tunnel descriptions.
-     */
-    Set<L2TunnelDescription> getL2Descriptions(boolean pending);
-
-    /**
-     * Returns a copy of the l2 policies that exist in the store.
-     *
-     * @return The l2 policies
-     */
-    List<L2TunnelPolicy> getL2Policies();
-
-    /**
-     * Returns a copy of the l2 tunnels that exist in the store.
-     *
-     * @return The l2 tunnels.
-     */
-    List<L2Tunnel> getL2Tunnels();
-
-    /**
-     * Returns a copy of the pending l2 policies that exist in the store.
-     *
-     * @return The l2 policies
-     */
-    List<L2TunnelPolicy> getL2PendingPolicies();
-
-    /**
-     * Helper function to handle the pw removal.
-     * <p>
-     * This method should for the mastership of the device because it is
-     * used only from network configuration updates, thus we only want
-     * one instance only to program each pseudowire.
-     *
-     * @param pwToRemove the pseudo wires to remove
-     * @deprecated onos-1.12 Do not use this method.
-     */
-    @Deprecated
-    void tearDown(Set<L2TunnelDescription> pwToRemove);
-
-    /**
-     * Returns a copy of the pending l2 tunnels that exist in the store.
-     *
-     * @return The l2 tunnels.
-     */
-    List<L2Tunnel> getL2PendingTunnels();
-
-    /**
-     * Verifies global validity for existing pseudowires, both ones in
-     * the pending store and the ones installed.
-     *
-     * @param pwToAdd the new pseudowire to add
-     * @return a Result describing the outcome
-     */
-    Result verifyGlobalValidity(L2TunnelDescription pwToAdd);
-
-    /**
-     * Check if pseudowire exists in the store.
-     *
-     * @param tunnelId The tunnel id to check for.
-     * @param pending Check in pending store for pseudowires.
-     * @return The result of the operation.
-     */
-    Result checkIfPwExists(long tunnelId, boolean pending);
-
-    /**
-     * Returns the PW init next objective store.
-     *
-     * @return current contents of the l2InitiationNextObjStore
-     */
-    ImmutableMap<String, NextObjective> getInitNext();
-
-    /**
-     * Returns the PW termination next objective store.
-     *
-     * @return current contents of the l2TerminationNextObjStore
-     */
-    ImmutableMap<String, NextObjective> getTermNext();
-
-    /**
-     * Removes given next ID from both PW init/term next obj store.
-     *
-     * @param nextId next ID
-     */
-    void removeNextId(int nextId);
-
-    /**
-     * Pwaas pipelines.
-     */
-    enum Pipeline {
-        /**
-         * The initiation pipeline.
-         */
-        INITIATION, /**
-         * The termination pipeline.
-         */
-        TERMINATION
-    }
-
-    /**
-     * Enum helper to carry results of various operations.
-     */
-    enum Result {
-        /**
-         * Happy ending scenario.
-         */
-        SUCCESS(0, "No error occurred"),
-
-        /**
-         * We have problems with the supplied parameters.
-         */
-        WRONG_PARAMETERS(1, "Wrong parameters"),
-
-        /**
-         * We have an internal error during the deployment
-         * or removal phase.
-         */
-        INTERNAL_ERROR(3, "Internal error"),
-
-        /**
-         * No path found between the connection points.
-         */
-        PATH_NOT_FOUND(7, "Could not find valid path between connection points!"),
-
-        /**
-         * Error in global pseudowires configuration.
-         */
-        CONFIGURATION_ERROR(8, "Conflicting pseudowire configurations!");
-
-        private final int code;
-        private final String description;
-
-        private String specificError;
-        private int nextId;
-
-        Result(int code, String description) {
-            this.code = code;
-            this.description = description;
-        }
-
-        public Result appendError(String error) {
-           this.specificError = error;
-           return this;
-        }
-
-        public String getSpecificError() {
-            return specificError;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-        public int getNextId() {
-            return nextId;
-        }
-
-        protected void setNextId(int nextId) {
-            this.nextId = nextId;
-        }
-
-        @Override
-        public String toString() {
-            return code + ": " + description;
-        }
-    }
-
-    /**
-     * Enum helper for handling the direction of the pw.
-     */
-    enum Direction {
-        /**
-         * The forward direction of the pseudo wire.
-         */
-        FWD, /**
-         * The reverse direction of the pseudo wire.
-         */
-        REV
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java
deleted file mode 100644
index 17be45b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2016-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.pwaas;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-public interface L2TunnelPolicy {
-
-    /**
-     * Returns the first connect point of the policy.
-     *
-     * @return first connect point
-     */
-    ConnectPoint cP1();
-
-    /**
-     * Returns the second connect point of the policy.
-     *
-     * @return second connect point
-     */
-    ConnectPoint cP2();
-
-    /**
-     * Returns the cP1 inner vlan tag of the policy.
-     *
-     * @return cP1 inner vlan tag
-     */
-    VlanId cP1InnerTag();
-
-    /**
-     * Returns the cP1 outer vlan tag of the policy.
-     *
-     * @return cP1 outer vlan tag
-     */
-    VlanId cP1OuterTag();
-
-    /**
-     * Returns the cP2 inner vlan tag of the policy.
-     *
-     * @return cP2 inner vlan tag
-     */
-    VlanId cP2InnerTag();
-
-    /**
-     * Returns the cP2 outer vlan tag of the policy.
-     *
-     * @return cP2 outer vlan tag
-     */
-    VlanId cP2OuterTag();
-
-    /**
-     * Returns the tunnel ID of the policy.
-     *
-     * @return Tunnel ID
-     */
-    long tunnelId();
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
deleted file mode 100644
index 7cb60a6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * 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.pwaas;
-
-import org.onlab.osgi.ServiceNotFoundException;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.intf.InterfaceService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * Utility class with static methods that help
- * parse pseudowire related information and also
- * verify that a pseudowire combination is valid.
- */
-public final class PwaasUtil {
-
-    private static final Logger log = LoggerFactory.getLogger(PwaasUtil.class);
-
-    private static DeviceService deviceService;
-    private static InterfaceService intfService;
-
-    // Suppress ExceptionInInitializerError and simply set the value to null,
-    // such that unit tests have a chance to replace the variable with mocked service
-    static {
-        try {
-            deviceService = AbstractShellCommand.get(DeviceService.class);
-        } catch (NullPointerException | ServiceNotFoundException e) {
-            deviceService = null;
-        }
-        try {
-            intfService = AbstractShellCommand.get(InterfaceService.class);
-        } catch (NullPointerException | ServiceNotFoundException e) {
-            intfService = null;
-        }
-    }
-
-    static final String ERR_SERVICE_UNAVAIL = "Service %s not available";
-    static final String ERR_SAME_DEV =
-            "Pseudowire connection points can not reside in the same node, in pseudowire %d.";
-    static final String ERR_EMPTY_INNER_WHEN_OUTER_PRESENT =
-            "Inner tag should not be empty when outer tag is set for pseudowire %d for %s.";
-    static final String ERR_WILDCARD_VLAN =
-            "Wildcard VLAN matching not yet supported for pseudowire %d.";
-    static final String ERR_DOUBLE_TO_UNTAGGED =
-            "Support for double tag <-> untag is not supported for pseudowire %d.";
-    static final String ERR_DOUBLE_TO_SINGLE =
-            "Support for double-tag<-> single-tag is not supported for pseudowire %d.";
-    static final String ERR_SINGLE_TO_UNTAGGED =
-            "single-tag <-> untag is not supported for pseudowire %d.";
-    static final String ERR_VLAN_TRANSLATION =
-            "We do not support VLAN translation for pseudowire %d.";
-    static final String ERR_DEV_NOT_FOUND =
-            "Device %s does not exist for pseudowire %d.";
-    static final String ERR_PORT_NOT_FOUND =
-            "Port %s of device %s does not exist for pseudowire %d.";
-
-    private PwaasUtil() {
-
-    }
-
-    /**
-     * Parses a vlan as a string. Returns the VlanId if
-     * provided String can be parsed as an integer or is '' / '*'
-     *
-     * @param vlan string as read from configuration
-     * @return VlanId null if error
-     */
-    public static VlanId parseVlan(String vlan) {
-
-        if (vlan.equals("*") || vlan.equals("Any")) {
-            return VlanId.vlanId("Any");
-        } else if (vlan.equals("") || vlan.equals("None")) {
-            return VlanId.vlanId("None");
-        } else {
-            return VlanId.vlanId(vlan);
-        }
-    }
-
-    /**
-     *
-     * @param mode RAW or TAGGED
-     * @return the L2Mode if input is correct
-     */
-    public static L2Mode parseMode(String mode) {
-        checkArgument(mode.equals("RAW") || mode.equals("TAGGED"),
-                      "Invalid pseudowire mode of operation, should be TAGGED or RAW.");
-        return L2Mode.valueOf(mode);
-    }
-
-    /**
-     *
-     * @param label the mpls label of the pseudowire
-     * @return the MplsLabel
-     * @throws IllegalArgumentException if label is invalid
-     */
-    public static MplsLabel parsePWLabel(String label) {
-        return MplsLabel.mplsLabel(label);
-    }
-
-    /**
-     * Parses a string as a pseudowire id - which is an integer.
-     *
-     * @param id The id of pw in string form
-     * @return The id of pw as an Integer or null if it failed the conversion.
-     */
-    public static Integer parsePwId(String id) {
-        return Integer.parseInt(id);
-    }
-
-    /**
-     * Helper method to verify if the tunnel is whether or not
-     * supported.
-     *
-     * @param l2Tunnel the tunnel to verify
-     */
-    private static void verifyTunnel(L2Tunnel l2Tunnel) {
-
-        // Service delimiting tag not supported yet.
-        if (!l2Tunnel.sdTag().equals(VlanId.NONE)) {
-            throw new IllegalArgumentException(String.format("Service delimiting tag not supported yet for " +
-                                                                     "pseudowire %d.", l2Tunnel.tunnelId()));
-        }
-
-        // Tag mode not supported yet.
-        if (l2Tunnel.pwMode() == L2Mode.TAGGED) {
-            throw new IllegalArgumentException(String.format("Tagged mode not supported yet for pseudowire %d.",
-                                                             l2Tunnel.tunnelId()));
-        }
-
-        // Raw mode without service delimiting tag
-        // is the only mode supported for now.
-    }
-
-    /**
-     * Helper method to verify if the policy is whether or not
-     * supported and if policy will be successfully instantiated in the
-     * network.
-     *
-     * @param cP1 pseudo wire endpoint 1
-     * @param cP2 pseudo wire endpoint 2
-     * @param ingressInner the ingress inner tag
-     * @param ingressOuter the ingress outer tag
-     * @param egressInner the egress inner tag
-     * @param egressOuter the egress outer tag
-     * @param tunnelId tunnel ID
-     */
-    static void verifyPolicy(ConnectPoint cP1,
-                              ConnectPoint cP2,
-                              VlanId ingressInner,
-                              VlanId ingressOuter,
-                              VlanId egressInner,
-                              VlanId egressOuter,
-                              Long tunnelId) {
-
-        if (cP1.deviceId().equals(cP2.deviceId())) {
-            throw new IllegalArgumentException(String.format(ERR_SAME_DEV, tunnelId));
-        }
-
-        // We can have multiple tags, all of them can be NONE,
-        // indicating untagged traffic, however, the outer tag can
-        // not have value if the inner tag is None
-        if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) {
-            throw new IllegalArgumentException(String.format(ERR_EMPTY_INNER_WHEN_OUTER_PRESENT,
-                    tunnelId, "cp1"));
-        }
-
-        if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) {
-            throw new IllegalArgumentException(String.format(ERR_EMPTY_INNER_WHEN_OUTER_PRESENT,
-                    tunnelId, "cp2"));
-        }
-
-        if (ingressInner.equals(VlanId.ANY) ||
-                ingressOuter.equals(VlanId.ANY) ||
-                egressInner.equals(VlanId.ANY) ||
-                egressOuter.equals(VlanId.ANY)) {
-            throw new IllegalArgumentException(String.format(ERR_WILDCARD_VLAN, tunnelId));
-        }
-
-        if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) &&
-                (egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE)))
-                || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) &&
-                (!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) {
-            throw new IllegalArgumentException(String.format(ERR_DOUBLE_TO_UNTAGGED, tunnelId));
-        }
-        if ((!ingressInner.equals(VlanId.NONE) &&
-                ingressOuter.equals(VlanId.NONE) &&
-                !egressOuter.equals(VlanId.NONE))
-                || (egressOuter.equals(VlanId.NONE) &&
-                !egressInner.equals(VlanId.NONE) &&
-                !ingressOuter.equals(VlanId.NONE))) {
-            throw new IllegalArgumentException(String.format(ERR_DOUBLE_TO_SINGLE, tunnelId));
-        }
-
-        if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE))
-                || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) {
-            throw new IllegalArgumentException(String.format(ERR_SINGLE_TO_UNTAGGED, tunnelId));
-        }
-
-        // FIXME PW VLAN translation is not supported on Dune
-        //       Need to explore doing that in egress table later if there is a requirement
-        if (!ingressInner.equals(egressInner) || !ingressOuter.equals(egressOuter)) {
-            throw new IllegalArgumentException(String.format(ERR_VLAN_TRANSLATION, tunnelId));
-        }
-
-        if (deviceService == null) {
-            throw new IllegalStateException(String.format(ERR_SERVICE_UNAVAIL, "DeviceService"));
-        }
-
-        // check if cp1 and port of cp1 exist
-        if (deviceService.getDevice(cP1.deviceId()) == null) {
-            throw new IllegalArgumentException(String.format(ERR_DEV_NOT_FOUND, cP1.deviceId(), tunnelId));
-        }
-
-        if (deviceService.getPort(cP1) == null) {
-            throw new IllegalArgumentException(String.format(ERR_PORT_NOT_FOUND, cP1.port(),
-                    cP1.deviceId(), tunnelId));
-        }
-
-        // check if cp2 and port of cp2 exist
-        if (deviceService.getDevice(cP2.deviceId()) == null) {
-            throw new IllegalArgumentException(String.format(ERR_DEV_NOT_FOUND, cP2.deviceId(), tunnelId));
-        }
-
-        if (deviceService.getPort(cP2) == null) {
-            throw new IllegalArgumentException(String.format(ERR_PORT_NOT_FOUND, cP2.port(),
-                    cP2.deviceId(), tunnelId));
-        }
-    }
-
-    /**
-     * Verifies that the pseudowires will not conflict with each other.
-     *
-     * Further, check if vlans for connect points are already used.
-     *
-     * @param tunnel Tunnel for pw
-     * @param policy Policy for pw
-     * @param labelSet Label set used so far with this configuration
-     * @param vlanSet Vlan set used with this configuration
-     * @param tunnelSet Tunnel set used with this configuration
-     */
-    private static void verifyGlobalValidity(L2Tunnel tunnel,
-                                      L2TunnelPolicy policy,
-                                      Set<MplsLabel> labelSet,
-                                      Map<ConnectPoint, Set<VlanId>> vlanSet,
-                                      Set<Long> tunnelSet) {
-
-        if (tunnelSet.contains(tunnel.tunnelId())) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Tunnel Id %d already used by" +
-                                                                                    " another pseudowire, in " +
-                                                                                    "pseudowire %d!",
-                                                                            tunnel.tunnelId(),
-                                                                            tunnel.tunnelId())));
-        }
-        tunnelSet.add(tunnel.tunnelId());
-
-        // check if tunnel id is used again
-        ConnectPoint cP1 = policy.cP1();
-        ConnectPoint cP2 = policy.cP2();
-
-        // insert cps to hashmap if this is the first time seen
-        if (!vlanSet.containsKey(cP1)) {
-            vlanSet.put(cP1, new HashSet<VlanId>());
-        }
-        if (!vlanSet.containsKey(cP2)) {
-            vlanSet.put(cP2, new HashSet<VlanId>());
-        }
-
-        // if single tagged or untagged vlan is the inner
-        // if double tagged vlan is the outer
-        VlanId vlanToCheckCP1;
-        if (policy.cP1OuterTag().equals(VlanId.NONE)) {
-            vlanToCheckCP1 = policy.cP1InnerTag();
-        } else {
-            vlanToCheckCP1 = policy.cP1OuterTag();
-        }
-
-        VlanId vlanToCheckCP2;
-        if (policy.cP2OuterTag().equals(VlanId.NONE)) {
-            vlanToCheckCP2 = policy.cP2InnerTag();
-        } else {
-            vlanToCheckCP2 = policy.cP2OuterTag();
-        }
-
-        if (labelSet.contains(tunnel.pwLabel())) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" +
-                                                                                    " pseudowire, in pseudowire %d!",
-                                                                            tunnel.pwLabel(), tunnel.tunnelId())));
-        }
-        labelSet.add(tunnel.pwLabel());
-
-        if (vlanSet.get(cP1).contains(vlanToCheckCP1)) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already used " +
-                                                                                    "by another pseudowire, in " +
-                                                                                    "pseudowire" +
-                                                                                    " %d!", vlanToCheckCP1,  cP1,
-                                                                            tunnel.tunnelId())));
-        }
-        vlanSet.get(cP1).add(vlanToCheckCP1);
-
-        if (vlanSet.get(cP2).contains(vlanToCheckCP2)) {
-            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already used" +
-                                                                                    " by another pseudowire, in" +
-                                                                                    " pseudowire %d!", vlanToCheckCP2,
-                                                                            cP2,
-                                                                            tunnel.tunnelId())));
-        }
-        vlanSet.get(cP2).add(vlanToCheckCP2);
-
-        if (intfService == null) {
-            throw new IllegalStateException(String.format(ERR_SERVICE_UNAVAIL, "InterfaceService"));
-        }
-
-        // check that vlans for the connect points are not used
-        intfService.getInterfacesByPort(cP1).stream()
-                .forEach(intf -> {
-
-                    // check if tagged pw affects tagged interface
-                    if (intf.vlanTagged().contains(vlanToCheckCP1)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already" +
-                                                                                                " used for this" +
-                                                                                                " interface, in" +
-                                                                                                " pseudowire %d!",
-                                                                                        vlanToCheckCP1, cP1,
-                                                                                        tunnel.tunnelId())));
-                    }
-
-                    // if vlanNative != null this interface is configured with untagged traffic also
-                    // check if it collides with untagged interface
-                    if ((intf.vlanNative() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP1 " +
-                                                                                                "%s already used " +
-                                                                                                "for this " +
-                                                                                                "interface, in " +
-                                                                                                "pseudowire " +
-                                                                                                "%d!", cP1,
-                                                                                        tunnel.tunnelId())));
-                    }
-
-                    // if vlanUntagged != null this interface is configured only with untagged traffic
-                    // check if it collides with untagged interface
-                    if ((intf.vlanUntagged() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for " +
-                                                                                                "cP1 %s already" +
-                                                                                                " used for this" +
-                                                                                                " interface," +
-                                                                                                " in pseudowire %d!",
-                                                                                        cP1, tunnel.tunnelId())));
-                    }
-                });
-
-        intfService.getInterfacesByPort(cP2).stream()
-                .forEach(intf -> {
-                    if (intf.vlanTagged().contains(vlanToCheckCP2)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s " +
-                                                                                                " used for  " +
-                                                                                                "this interface, " +
-                                                                                                "in pseudowire %d!",
-                                                                                        vlanToCheckCP2, cP2,
-                                                                                        tunnel.tunnelId())));
-                    }
-
-                    // if vlanNative != null this interface is configured with untagged traffic also
-                    // check if it collides with untagged interface
-                    if ((intf.vlanNative() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic " +
-                                                                                                "for cP2 %s " +
-                                                                                                "already " +
-                                                                                                "used for this" +
-                                                                                                " interface, " +
-                                                                                                "in pseudowire %d!",
-                                                                                        cP2, tunnel.tunnelId())));
-                    }
-
-                    // if vlanUntagged != null this interface is configured only with untagged traffic
-                    // check if it collides with untagged interface
-                    if ((intf.vlanUntagged() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
-                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s" +
-                                                                                                " already" +
-                                                                                                " used for " +
-                                                                                                "this interface, " +
-                                                                                                "in pseudowire %d!",
-                                                                                        cP2, tunnel.tunnelId())));
-                    }
-                });
-
-    }
-
-    /**
-     * Helper method to verify the integrity of the pseudo wire.
-     *
-     * @param l2TunnelDescription the pseudo wire description
-     */
-    private static void verifyPseudoWire(L2TunnelDescription l2TunnelDescription,
-                                  Set<MplsLabel> labelSet,
-                                  Map<ConnectPoint, Set<VlanId>> vlanset,
-                                  Set<Long> tunnelSet) {
-
-        L2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel();
-        L2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy();
-
-        verifyTunnel(l2Tunnel);
-
-        verifyPolicy(
-                l2TunnelPolicy.cP1(),
-                l2TunnelPolicy.cP2(),
-                l2TunnelPolicy.cP1InnerTag(),
-                l2TunnelPolicy.cP1OuterTag(),
-                l2TunnelPolicy.cP2InnerTag(),
-                l2TunnelPolicy.cP2OuterTag(),
-                l2Tunnel.tunnelId()
-        );
-
-        verifyGlobalValidity(l2Tunnel,
-                             l2TunnelPolicy,
-                             labelSet,
-                             vlanset,
-                             tunnelSet);
-
-    }
-
-    public static L2TunnelHandler.Result configurationValidity(List<L2TunnelDescription> pseudowires) {
-
-        // structures to keep pw information
-        // in order to see if instantiating them will create
-        // problems
-        Set<Long> tunIds = new HashSet<>();
-        Set<MplsLabel> labelsUsed = new HashSet<>();
-        Map<ConnectPoint, Set<VlanId>> vlanIds = new HashMap<>();
-
-        // TODO : I know we should not use exceptions for flow control,
-        // however this code was originally implemented in the configuration
-        // addition where the exceptions were propagated and the configuration was
-        // deemed not valid. I plan in the future to refactor the parts that
-        // check the pseudowire validity.
-        //
-        // Ideally we would like to return a String which could also return to
-        // the user issuing the rest request for adding the pseudowire.
-        try {
-            // check that pseudowires can be instantiated in the network
-            // we try to guarantee that all the pws will work before
-            // instantiating any of them
-            for (L2TunnelDescription pw : pseudowires) {
-                log.debug("Verifying pseudowire {}", pw);
-                verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds);
-            }
-
-            return L2TunnelHandler.Result.SUCCESS;
-        } catch (Exception e) {
-            log.error("Caught exception while validating pseudowire : {}", e.getMessage());
-            return L2TunnelHandler.Result.CONFIGURATION_ERROR
-                    .appendError(e.getMessage());
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/package-info.java
deleted file mode 100644
index 463b163..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2016-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.
- */
-
-/**
- * Set of resources implementing the Pwaas.
- */
-package org.onosproject.segmentrouting.pwaas;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/DestinationSetNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/DestinationSetNextObjectiveStoreKey.java
deleted file mode 100644
index 0baa769..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/DestinationSetNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2016-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/licedses/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.storekey;
-
-import java.util.Objects;
-
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of Destination set next objective store.
- */
-public class DestinationSetNextObjectiveStoreKey {
-    private final DeviceId deviceId;
-    private final DestinationSet ds;
-
-    /**
-     * Constructs the key of destination set next objective store.
-     *
-     * @param deviceId device ID
-     * @param ds destination set
-     */
-    public DestinationSetNextObjectiveStoreKey(DeviceId deviceId,
-                                            DestinationSet ds) {
-        this.deviceId = deviceId;
-        this.ds = ds;
-    }
-
-    /**
-     * Returns the device ID in the key.
-     *
-     * @return device ID
-     */
-    public DeviceId deviceId() {
-        return this.deviceId;
-    }
-
-    /**
-     * Returns the destination set in the key.
-     *
-     * @return destination set
-     */
-    public DestinationSet destinationSet() {
-        return this.ds;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof DestinationSetNextObjectiveStoreKey)) {
-            return false;
-        }
-        DestinationSetNextObjectiveStoreKey that =
-                (DestinationSetNextObjectiveStoreKey) o;
-        return (Objects.equals(this.deviceId, that.deviceId) &&
-                Objects.equals(this.ds, that.ds));
-    }
-
-    // The list of destination ids and label are used for comparison.
-    @Override
-    public int hashCode() {
-        int result = 17;
-        result = 31 * result + Objects.hashCode(this.deviceId)
-                + Objects.hashCode(this.ds);
-
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("deviceId", deviceId)
-                .add("ds", ds)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/MacVlanNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/MacVlanNextObjectiveStoreKey.java
deleted file mode 100644
index 4a1ab78..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/MacVlanNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2019-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.storekey;
-
-import org.onlab.packet.VlanId;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of Device/Vlan/MacAddr to NextObjective store.
- */
-public class MacVlanNextObjectiveStoreKey {
-    private final DeviceId deviceId;
-    private final MacAddress macAddr;
-    private final VlanId vlanId;
-
-    /**
-     * Constructs the key of the next objective store.
-     *
-     * @param deviceId device ID
-     * @param macAddr mac of host
-     * @param vlanId vlan of host
-     */
-    public MacVlanNextObjectiveStoreKey(DeviceId deviceId, MacAddress macAddr, VlanId vlanId) {
-        this.deviceId = deviceId;
-        this.macAddr = macAddr;
-        this.vlanId = vlanId;
-    }
-
-    /**
-     * Gets device id in this MacVlanNextObjectiveStoreKey.
-     *
-     * @return device id
-     */
-    public DeviceId deviceId() {
-        return deviceId;
-    }
-
-    /**
-     * Gets vlan information in this MacVlanNextObjectiveStoreKey.
-     *
-     * @return vlan information
-     */
-    public VlanId vlanId() {
-        return vlanId;
-    }
-
-    /**
-     * Gets mac information in this MacVlanNextObjectiveStoreKey.
-     *
-     * @return mac information
-     */
-    public MacAddress macAddr() {
-        return macAddr;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof MacVlanNextObjectiveStoreKey)) {
-            return false;
-        }
-        MacVlanNextObjectiveStoreKey that =
-                (MacVlanNextObjectiveStoreKey) o;
-        return (Objects.equals(this.deviceId, that.deviceId) &&
-                Objects.equals(this.vlanId, that.vlanId) &&
-                Objects.equals(this.macAddr, that.macAddr));
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(deviceId, vlanId, macAddr);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("deviceId", deviceId)
-                .add("vlanId", vlanId)
-                .add("macAddr", macAddr)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/PortNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/PortNextObjectiveStoreKey.java
deleted file mode 100644
index 1269bce..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/PortNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2016-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.storekey;
-
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of Device/Port to NextObjective store.
- *
- * Since there can be multiple next objectives to the same physical port,
- * we differentiate between them by including the treatment in the key.
- */
-public class PortNextObjectiveStoreKey {
-    private final DeviceId deviceId;
-    private final PortNumber portNum;
-    private final TrafficTreatment treatment;
-    private final TrafficSelector meta;
-
-    /**
-     * Constructs the key of port next objective store.
-     *
-     * @param deviceId device ID
-     * @param portNum port number
-     * @param treatment treatment that will be applied to the interface
-     * @param meta optional data to pass to the driver
-     */
-    public PortNextObjectiveStoreKey(DeviceId deviceId, PortNumber portNum,
-                                     TrafficTreatment treatment,
-                                     TrafficSelector meta) {
-        this.deviceId = deviceId;
-        this.portNum = portNum;
-        this.treatment = treatment;
-        this.meta = meta;
-    }
-
-    /**
-     * Gets device id in this PortNextObjectiveStoreKey.
-     *
-     * @return device id
-     */
-    public DeviceId deviceId() {
-        return deviceId;
-    }
-
-    /**
-     * Gets port information in this PortNextObjectiveStoreKey.
-     *
-     * @return port information
-     */
-    public PortNumber portNumber() {
-        return portNum;
-    }
-
-    /**
-     * Gets treatment information in this PortNextObjectiveStoreKey.
-     *
-     * @return treatment information
-     */
-    public TrafficTreatment treatment() {
-        return treatment;
-    }
-
-    /**
-     * Gets metadata information in this PortNextObjectiveStoreKey.
-     *
-     * @return meta information
-     */
-    public TrafficSelector meta() {
-        return meta;
-    }
-
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof PortNextObjectiveStoreKey)) {
-            return false;
-        }
-        PortNextObjectiveStoreKey that =
-                (PortNextObjectiveStoreKey) o;
-        return (Objects.equals(this.deviceId, that.deviceId) &&
-                Objects.equals(this.portNum, that.portNum) &&
-                Objects.equals(this.treatment, that.treatment) &&
-                Objects.equals(this.meta, that.meta));
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(deviceId, portNum, treatment, meta);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("deviceId", deviceId)
-                .add("portNum", portNum)
-                .add("treatment", treatment)
-                .add("meta", meta)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java
deleted file mode 100644
index 55a95cd..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2016-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.storekey;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of VLAN to NextObjective store.
- */
-public class VlanNextObjectiveStoreKey {
-    private final DeviceId deviceId;
-    private final VlanId vlanId;
-
-    /**
-     * Constructs the key of VLAN next objective store.
-     *
-     * @param deviceId device ID
-     * @param vlanId VLAN information
-     */
-    public VlanNextObjectiveStoreKey(DeviceId deviceId,
-                                     VlanId vlanId) {
-        this.deviceId = deviceId;
-        this.vlanId = vlanId;
-    }
-
-    /**
-     * Gets device id in this VlanNextObjectiveStoreKey.
-     *
-     * @return device id
-     */
-    public DeviceId deviceId() {
-        return this.deviceId;
-    }
-
-    /**
-     * Gets vlan information in this VlanNextObjectiveStoreKey.
-     *
-     * @return vlan id
-     */
-    public VlanId vlanId() {
-        return this.vlanId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof VlanNextObjectiveStoreKey)) {
-            return false;
-        }
-        VlanNextObjectiveStoreKey that =
-                (VlanNextObjectiveStoreKey) o;
-        return (Objects.equals(this.deviceId, that.deviceId) &&
-                Objects.equals(this.vlanId, that.vlanId));
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(deviceId, vlanId);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(getClass())
-                .add("deviceId", deviceId)
-                .add("vlanId", vlanId)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/XConnectStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/XConnectStoreKey.java
deleted file mode 100644
index 0e90a22..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/XConnectStoreKey.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2016-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.storekey;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Key of VLAN cross-connect next objective store.
- */
-public class XConnectStoreKey {
-    private final DeviceId deviceId;
-    private final VlanId vlanId;
-
-    /**
-     * Constructs the key of cross-connect next objective store.
-     *
-     * @param deviceId device ID of the VLAN cross-connection
-     * @param vlanId VLAN ID of the VLAN cross-connection
-     */
-    public XConnectStoreKey(DeviceId deviceId, VlanId vlanId) {
-        this.deviceId = deviceId;
-        this.vlanId = vlanId;
-    }
-
-    /**
-     * Returns the device ID of this key.
-     *
-     * @return device ID
-     */
-    public DeviceId deviceId() {
-        return this.deviceId;
-    }
-
-    /**
-     * Returns the VLAN ID of this key.
-     *
-     * @return VLAN ID
-     */
-    public VlanId vlanId() {
-        return this.vlanId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof XConnectStoreKey)) {
-            return false;
-        }
-        XConnectStoreKey that =
-                (XConnectStoreKey) o;
-        return (Objects.equals(this.deviceId, that.deviceId) &&
-                Objects.equals(this.vlanId, that.vlanId));
-    }
-
-    // The list of neighbor ids and label are used for comparison.
-    @Override
-    public int hashCode() {
-         return Objects.hash(deviceId, vlanId);
-    }
-
-    @Override
-    public String toString() {
-        return "Device: " + deviceId + " VlanId: " + vlanId;
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/package-info.java
deleted file mode 100644
index 44fc6a7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2016-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.
- */
-
-/**
- * Key data structure of various stores used by Segment Routing.
- */
-package org.onosproject.segmentrouting.storekey;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodec.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodec.java
deleted file mode 100644
index 83421bc..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodec.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2018-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.xconnect.api;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.Sets;
-import org.onlab.packet.VlanId;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import org.onosproject.net.DeviceId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-
-/**
- * Codec for Xconnect.
- */
-public class XconnectCodec extends JsonCodec<XconnectDesc> {
-    static final String DEVICE_ID = "deviceId";
-    static final String VLAN_ID = "vlanId";
-    static final String ENDPOINTS = "endpoints";
-
-    private static Logger log = LoggerFactory.getLogger(XconnectCodec.class);
-
-    @Override
-    public ObjectNode encode(XconnectDesc desc, CodecContext context) {
-        final ObjectNode result = context.mapper().createObjectNode();
-        result.put(DEVICE_ID, desc.key().deviceId().toString());
-        result.put(VLAN_ID, desc.key().vlanId().toShort());
-        final ArrayNode portNode = result.putArray(ENDPOINTS);
-        desc.endpoints().forEach(endpoint -> portNode.add(endpoint.toString()));
-
-        return result;
-    }
-
-    @Override
-    public XconnectDesc decode(ObjectNode json, CodecContext context) {
-        DeviceId deviceId = DeviceId.deviceId(json.path(DEVICE_ID).asText());
-        VlanId vlanId = VlanId.vlanId(json.path(VLAN_ID).asText());
-
-        Set<XconnectEndpoint> endpoints = Sets.newHashSet();
-        JsonNode endpointNodes = json.get(ENDPOINTS);
-        if (endpointNodes != null) {
-            endpointNodes.forEach(endpointNode -> endpoints.add(XconnectEndpoint.fromString(endpointNode.asText())));
-        }
-
-        XconnectKey key = new XconnectKey(deviceId, vlanId);
-        return new XconnectDesc(key, endpoints);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectDesc.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectDesc.java
deleted file mode 100644
index a47823a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectDesc.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2018-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.xconnect.api;
-
-import com.google.common.base.MoreObjects;
-
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Xconnect description.
- */
-public class XconnectDesc {
-    private XconnectKey key;
-    private Set<XconnectEndpoint> endpoints;
-
-    /**
-     * Constructs new Xconnect description with given device ID and VLAN ID.
-     *
-     * @param key Xconnect key
-     * @param endpoints set of endpoints
-     */
-    public XconnectDesc(XconnectKey key, Set<XconnectEndpoint> endpoints) {
-        this.key = key;
-        this.endpoints = endpoints;
-    }
-
-    /**
-     * Gets Xconnect key.
-     *
-     * @return Xconnect key
-     */
-    public XconnectKey key() {
-        return key;
-    }
-
-    /**
-     * Gets endpoints.
-     *
-     * @return set of endpoints
-     */
-    public Set<XconnectEndpoint> endpoints() {
-        return endpoints;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof XconnectDesc)) {
-            return false;
-        }
-        final XconnectDesc other = (XconnectDesc) obj;
-        return Objects.equals(this.key, other.key) &&
-                Objects.equals(this.endpoints, other.endpoints);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(key, endpoints);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .add("key", key)
-                .add("endpoints", endpoints)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectEndpoint.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectEndpoint.java
deleted file mode 100644
index c7a2242..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectEndpoint.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2019-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.xconnect.api;
-
-/**
- * Represents cross connect endpoint.
- */
-public abstract class XconnectEndpoint {
-    public static final String LB_KEYWORD = "LB:";
-    static final String PORT_PATTERN = "^\\d+$";
-    static final String LOAD_BALANCER_PATTERN = "^" + LB_KEYWORD + "\\d+$";
-
-    /**
-     * Types of endpoint.
-     */
-    public enum Type {
-        /**
-         * The endpoint is specified by an port number.
-         */
-        PORT,
-
-        /**
-         * The endpoint is specified by a load balancer.
-         */
-        LOAD_BALANCER
-    }
-
-    /**
-     * Type of this endpoint.
-     *
-     * @return type
-     */
-    public abstract XconnectEndpoint.Type type();
-
-    /**
-     * Constructs XconnectEndpoint from string.
-     *
-     * @param s string
-     * @return XconnectEndpoint
-     * @throws IllegalArgumentException if given string is in a wrong format
-     */
-    public static XconnectEndpoint fromString(String s) {
-        if (s.matches(XconnectEndpoint.PORT_PATTERN)) {
-            return XconnectPortEndpoint.fromString(s);
-        } else if (s.matches(XconnectEndpoint.LOAD_BALANCER_PATTERN)) {
-            return XconnectLoadBalancerEndpoint.fromString(s);
-        } else {
-            throw new IllegalArgumentException("Illegal endpoint format: " + s);
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectKey.java
deleted file mode 100644
index 7d433cd..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectKey.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2018-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.xconnect.api;
-
-import com.google.common.base.MoreObjects;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Xconnect key.
- */
-public class XconnectKey {
-    private DeviceId deviceId;
-    private VlanId vlanId;
-
-    /**
-     * Constructs new XconnectKey with given device ID and VLAN ID.
-     *
-     * @param deviceId device ID
-     * @param vlanId vlan ID
-     */
-    public XconnectKey(DeviceId deviceId, VlanId vlanId) {
-        this.deviceId = deviceId;
-        this.vlanId = vlanId;
-    }
-
-    /**
-     * Gets device ID.
-     *
-     * @return device ID of the Xconnect key
-     */
-    public DeviceId deviceId() {
-        return deviceId;
-    }
-
-    /**
-     * Gets VLAN ID.
-     *
-     * @return VLAN ID of the Xconnect key
-     */
-    public VlanId vlanId() {
-        return vlanId;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof XconnectKey)) {
-            return false;
-        }
-        final XconnectKey other = (XconnectKey) obj;
-        return Objects.equals(this.deviceId, other.deviceId) &&
-                Objects.equals(this.vlanId, other.vlanId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(deviceId, vlanId);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .add("deviceId", deviceId)
-                .add("vlanId", vlanId)
-                .toString();
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectLoadBalancerEndpoint.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectLoadBalancerEndpoint.java
deleted file mode 100644
index 4172292f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectLoadBalancerEndpoint.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2019-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.xconnect.api;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * Represents a cross connect endpoint specified by load balancer.
- */
-public final class XconnectLoadBalancerEndpoint extends XconnectEndpoint {
-    private final int key;
-
-    private XconnectLoadBalancerEndpoint(int key) {
-        this.key = key;
-    }
-
-    /**
-     * Returns load balancer key.
-     *
-     * @return load balancer key.
-     */
-    public int key() {
-        return key;
-    }
-
-    /**
-     * Returns an instance of XconnectLoadBalancerEndpoint with given load balancer key.
-     *
-     * @param key load balancer key
-     * @return an instance of XconnectLoadBalancerEndpoint
-     */
-    public static XconnectLoadBalancerEndpoint of(int key) {
-        return new XconnectLoadBalancerEndpoint(key);
-    }
-
-    /**
-     * Gets XconnectLoadBalancerEndpoint from string.
-     *
-     * @param s string
-     * @return XconnectLoadBalancerEndpoint
-     */
-    public static XconnectLoadBalancerEndpoint fromString(String s) {
-        checkArgument(s.matches(LOAD_BALANCER_PATTERN), "String {} does not match {} format", s, LOAD_BALANCER_PATTERN);
-        return new XconnectLoadBalancerEndpoint(Integer.valueOf(s.replaceFirst(LB_KEYWORD, "")));
-    }
-
-    @Override
-    public Type type() {
-        return Type.LOAD_BALANCER;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(key);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof XconnectLoadBalancerEndpoint) {
-            final XconnectLoadBalancerEndpoint other = (XconnectLoadBalancerEndpoint) obj;
-            return Objects.equals(this.key, other.key);
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return LB_KEYWORD + String.valueOf(key);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectPortEndpoint.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectPortEndpoint.java
deleted file mode 100644
index f26eaf0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectPortEndpoint.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2019-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.xconnect.api;
-
-import org.onosproject.net.PortNumber;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * Represents a cross connect endpoint specified by port number.
- */
-public final class XconnectPortEndpoint extends XconnectEndpoint {
-    private final PortNumber port;
-
-    private XconnectPortEndpoint(PortNumber port) {
-        this.port = port;
-    }
-
-    /**
-     * Returns port number.
-     *
-     * @return port number
-     */
-    public PortNumber port() {
-        return port;
-    }
-
-    /**
-     * Returns an instance of XconnectPortEndpoint with given port number.
-     *
-     * @param port port number
-     * @return an instance of XconnectPortEndpoint
-     */
-    public static XconnectPortEndpoint of(PortNumber port) {
-        return new XconnectPortEndpoint(port);
-    }
-
-    /**
-     * Gets XconnectPortEndpoint from string.
-     *
-     * @param s string
-     * @return XconnectPortEndpoint
-     */
-    public static XconnectPortEndpoint fromString(String s) {
-        checkArgument(s.matches(PORT_PATTERN), "String {} does not match {} format", s, PORT_PATTERN);
-        return new XconnectPortEndpoint(PortNumber.fromString(s));
-    }
-
-    @Override
-    public XconnectEndpoint.Type type() {
-        return Type.PORT;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(port);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof XconnectPortEndpoint) {
-            final XconnectPortEndpoint other = (XconnectPortEndpoint) obj;
-            return Objects.equals(this.port, other.port);
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return String.valueOf(port);
-    }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectService.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectService.java
deleted file mode 100644
index 2fe6488..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectService.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2018-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.xconnect.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * VLAN cross connect between exactly two ports.
- */
-public interface XconnectService {
-
-    /**
-     * VLAN cross-connect ACL priority.
-     */
-    int XCONNECT_ACL_PRIORITY = 60000;
-
-    /**
-     * VLAN cross-connect Bridging priority.
-     */
-    int XCONNECT_PRIORITY = 1000;
-
-    /**
-     * Creates or updates Xconnect.
-     *
-     * @param deviceId device ID
-     * @param vlanId VLAN ID
-     * @param endpoints set of endpoints
-     */
-    void addOrUpdateXconnect(DeviceId deviceId, VlanId vlanId, Set<XconnectEndpoint> endpoints);
-
-    /**
-     * Deletes Xconnect.
-     *
-     * @param deviceId device ID
-     * @param vlanId VLAN ID
-     */
-    void removeXonnect(DeviceId deviceId, VlanId vlanId);
-
-    /**
-     * Gets Xconnects.
-     *
-     * @return set of Xconnect descriptions
-     */
-    Set<XconnectDesc> getXconnects();
-
-    /**
-     * Check if there is Xconnect configured on given connect point.
-     *
-     * @param cp connect point
-     * @return true if there is Xconnect configured on the connect point
-     */
-    boolean hasXconnect(ConnectPoint cp);
-
-    /**
-     * Gives xconnect VLAN of given port of a device.
-     *
-     * @param deviceId Device ID
-     * @param port Port number
-     * @return true if given VLAN vlanId is XConnect VLAN on device deviceId.
-     */
-    List<VlanId> getXconnectVlans(DeviceId deviceId, PortNumber port);
-
-    /**
-     * Checks given VLAN is XConnect VLAN in given device.
-     *
-     * @param deviceId Device ID
-     * @param vlanId VLAN ID
-     * @return true if given VLAN vlanId is XConnect VLAN on device deviceId.
-     */
-    boolean isXconnectVlan(DeviceId deviceId, VlanId vlanId);
-
-    /**
-     * Returns the Xconnect next objective store.
-     *
-     * @return current contents of the xconnectNextObjStore
-     */
-    ImmutableMap<XconnectKey, Integer> getNext();
-
-    /**
-     * Removes given next ID from Xconnect next objective store.
-     *
-     * @param nextId next ID
-     */
-    void removeNextId(int nextId);
-
-    /**
-     * Returns Xconnect next objective ID associated with group device + vlan.
-     *
-     * @param deviceId - Device ID
-     * @param vlanId - VLAN ID
-     * @return Current associated group ID
-     */
-    int getNextId(DeviceId deviceId, VlanId vlanId);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/package-info.java
deleted file mode 100644
index 56df706..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2018-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.
- */
-
-/**
- * VLAN cross connect API.
- */
-package org.onosproject.segmentrouting.xconnect.api;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/XconnectManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/XconnectManager.java
deleted file mode 100644
index fecba5a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/XconnectManager.java
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * Copyright 2018-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.xconnect.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.LeadershipService;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.codec.CodecService;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerEvent;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerId;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerListener;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerService;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.Port;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultNextTreatment;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.IdNextTreatment;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.NextTreatment;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectCodec;
-import org.onosproject.segmentrouting.xconnect.api.XconnectDesc;
-import org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectLoadBalancerEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectPortEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.MapEvent;
-import org.onosproject.store.service.MapEventListener;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.Versioned;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.Iterator;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-
-@Component(immediate = true, service = XconnectService.class)
-public class XconnectManager implements XconnectService {
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private CoreService coreService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private CodecService codecService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private StorageService storageService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public NetworkConfigService netCfgService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public DeviceService deviceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public FlowObjectiveService flowObjectiveService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private LeadershipService leadershipService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private ClusterService clusterService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public MastershipService mastershipService;
-
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL)
-    public SegmentRoutingService srService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public InterfaceService interfaceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    HostService hostService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    private PortLoadBalancerService portLoadBalancerService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public NetworkConfigRegistry cfgService;
-
-    private static final String APP_NAME = "org.onosproject.xconnect";
-    private static final String ERROR_NOT_LEADER = "Not leader controller";
-    private static final String ERROR_NEXT_OBJ_BUILDER = "Unable to construct next objective builder";
-    private static final String ERROR_NEXT_ID = "Unable to get next id";
-    private static final String ERROR_NOT_EDGE_ROUTER = "Device is not Edge Router";
-    private static final String ERROR_PORT_NOT_RANGE = "Ports for the device are not in the range";
-
-    private static Logger log = LoggerFactory.getLogger(XconnectManager.class);
-
-    private ApplicationId appId;
-    private ConsistentMap<XconnectKey, Set<XconnectEndpoint>> xconnectStore;
-    private ConsistentMap<XconnectKey, Integer> xconnectNextObjStore;
-
-    private ConsistentMap<VlanNextObjectiveStoreKey, Integer> xconnectMulticastNextStore;
-    private ConsistentMap<VlanNextObjectiveStoreKey, List<PortNumber>> xconnectMulticastPortsStore;
-
-    private final MapEventListener<XconnectKey, Set<XconnectEndpoint>> xconnectListener = new XconnectMapListener();
-    private ExecutorService xConnectExecutor;
-
-    private final DeviceListener deviceListener = new InternalDeviceListener();
-    private ExecutorService deviceEventExecutor;
-
-    private final HostListener hostListener = new InternalHostListener();
-    private ExecutorService hostEventExecutor;
-
-    // Wait time for the cache
-    private static final int WAIT_TIME_MS = 15000;
-    //The cache is implemented as buffer for waiting the installation of PortLoadBalancer when present
-    private Cache<PortLoadBalancerId, XconnectKey> portLoadBalancerCache;
-    // Executor for the cache
-    private ScheduledExecutorService portLoadBalancerExecutor;
-    // We need to listen for some events to properly installed the xconnect with portloadbalancer
-    private final PortLoadBalancerListener portLoadBalancerListener = new InternalPortLoadBalancerListener();
-
-    @Activate
-    void activate() {
-        appId = coreService.registerApplication(APP_NAME);
-        codecService.registerCodec(XconnectDesc.class, new XconnectCodec());
-
-        KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
-                .register(KryoNamespaces.API)
-                .register(XconnectManager.class)
-                .register(XconnectKey.class)
-                .register(XconnectEndpoint.class)
-                .register(XconnectPortEndpoint.class)
-                .register(XconnectLoadBalancerEndpoint.class)
-                .register(VlanNextObjectiveStoreKey.class);
-
-        xconnectStore = storageService.<XconnectKey, Set<XconnectEndpoint>>consistentMapBuilder()
-                .withName("onos-sr-xconnect")
-                .withRelaxedReadConsistency()
-                .withSerializer(Serializer.using(serializer.build()))
-                .build();
-        xConnectExecutor = Executors.newSingleThreadScheduledExecutor(
-                groupedThreads("sr-xconnect-event", "%d", log));
-        xconnectStore.addListener(xconnectListener, xConnectExecutor);
-
-        xconnectNextObjStore = storageService.<XconnectKey, Integer>consistentMapBuilder()
-                .withName("onos-sr-xconnect-next")
-                .withRelaxedReadConsistency()
-                .withSerializer(Serializer.using(serializer.build()))
-                .build();
-
-        xconnectMulticastNextStore = storageService.<VlanNextObjectiveStoreKey, Integer>consistentMapBuilder()
-                .withName("onos-sr-xconnect-l2multicast-next")
-                .withSerializer(Serializer.using(serializer.build()))
-                .build();
-        xconnectMulticastPortsStore = storageService.<VlanNextObjectiveStoreKey, List<PortNumber>>consistentMapBuilder()
-                .withName("onos-sr-xconnect-l2multicast-ports")
-                .withSerializer(Serializer.using(serializer.build()))
-                .build();
-
-        deviceEventExecutor = Executors.newSingleThreadScheduledExecutor(
-                groupedThreads("sr-xconnect-device-event", "%d", log));
-        deviceService.addListener(deviceListener);
-
-        hostEventExecutor = Executors.newSingleThreadExecutor(
-                groupedThreads("sr-xconnect-host-event", "%d", log));
-        hostService.addListener(hostListener);
-
-        portLoadBalancerCache = CacheBuilder.newBuilder()
-                .expireAfterWrite(WAIT_TIME_MS, TimeUnit.MILLISECONDS)
-                .removalListener((RemovalNotification<PortLoadBalancerId, XconnectKey> notification) ->
-                        log.debug("PortLoadBalancer cache removal event. portLoadBalancerId={}, xConnectKey={}",
-                                                   notification.getKey(), notification.getValue())).build();
-        portLoadBalancerExecutor = newScheduledThreadPool(1,
-                                              groupedThreads("portLoadBalancerCacheWorker", "-%d", log));
-        // Let's schedule the cleanup of the cache
-        portLoadBalancerExecutor.scheduleAtFixedRate(portLoadBalancerCache::cleanUp, 0,
-                                         WAIT_TIME_MS, TimeUnit.MILLISECONDS);
-        portLoadBalancerService.addListener(portLoadBalancerListener);
-
-        log.info("Started");
-    }
-
-    @Deactivate
-    void deactivate() {
-        xconnectStore.removeListener(xconnectListener);
-        deviceService.removeListener(deviceListener);
-        hostService.removeListener(hostListener);
-        portLoadBalancerService.removeListener(portLoadBalancerListener);
-        codecService.unregisterCodec(XconnectDesc.class);
-
-        deviceEventExecutor.shutdown();
-        hostEventExecutor.shutdown();
-        xConnectExecutor.shutdown();
-        portLoadBalancerExecutor.shutdown();
-
-        log.info("Stopped");
-    }
-
-    @Override
-    public void addOrUpdateXconnect(DeviceId deviceId, VlanId vlanId, Set<XconnectEndpoint> endpoints) {
-        log.info("Adding or updating xconnect. deviceId={}, vlanId={}, endpoints={}",
-                 deviceId, vlanId, endpoints);
-        SegmentRoutingDeviceConfig config = cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
-
-        List<PortNumber> devicePorts = deviceService.getPorts(deviceId).stream()
-                .map(Port::number)
-                .collect(Collectors.toList());
-        if (!config.isEdgeRouter()) {
-            throw new IllegalArgumentException(ERROR_NOT_EDGE_ROUTER);
-        } else {
-                Iterator<XconnectEndpoint> itr = endpoints.iterator();
-                while (itr.hasNext()) {
-                    XconnectEndpoint ep = itr.next();
-                    // Note: we don't validate an endpoint with LOAD_BALANCER type
-                    if (ep.type() != XconnectEndpoint.Type.PORT) {
-                        continue;
-                    }
-                    if (!devicePorts.contains(((XconnectPortEndpoint) ep).port())) {
-                        throw new IllegalArgumentException(ERROR_PORT_NOT_RANGE);
-                    }
-                }
-        }
-        final XconnectKey key = new XconnectKey(deviceId, vlanId);
-        xconnectStore.put(key, endpoints);
-    }
-
-    @Override
-    public void removeXonnect(DeviceId deviceId, VlanId vlanId) {
-        log.info("Removing xconnect. deviceId={}, vlanId={}",
-                 deviceId, vlanId);
-        final XconnectKey key = new XconnectKey(deviceId, vlanId);
-        xconnectStore.remove(key);
-
-        // Cleanup multicasting support, if any.
-        srService.getPairDeviceId(deviceId).ifPresent(pairDeviceId ->
-            cleanupL2MulticastRule(pairDeviceId, srService.getPairLocalPort(pairDeviceId).get(), vlanId, true)
-        );
-
-    }
-
-    @Override
-    public Set<XconnectDesc> getXconnects() {
-        return xconnectStore.asJavaMap().entrySet().stream()
-                .map(e -> new XconnectDesc(e.getKey(), e.getValue()))
-                .collect(Collectors.toSet());
-    }
-
-    @Override
-    public boolean hasXconnect(ConnectPoint cp) {
-        return getXconnects().stream().anyMatch(desc ->
-                desc.key().deviceId().equals(cp.deviceId()) && desc.endpoints().stream().anyMatch(ep ->
-                        ep.type() == XconnectEndpoint.Type.PORT && ((XconnectPortEndpoint) ep).port().equals(cp.port())
-                )
-        );
-    }
-
-    @Override
-    public List<VlanId> getXconnectVlans(DeviceId deviceId, PortNumber port) {
-        return getXconnects().stream()
-                .filter(desc -> desc.key().deviceId().equals(deviceId) && desc.endpoints().stream().anyMatch(ep ->
-                        ep.type() == XconnectEndpoint.Type.PORT && ((XconnectPortEndpoint) ep).port().equals(port)))
-                .map(XconnectDesc::key)
-                .map(XconnectKey::vlanId)
-                .collect(Collectors.toList());
-    }
-
-    @Override
-    public boolean isXconnectVlan(DeviceId deviceId, VlanId vlanId) {
-        XconnectKey key = new XconnectKey(deviceId, vlanId);
-        return Versioned.valueOrNull(xconnectStore.get(key)) != null;
-    }
-
-    @Override
-    public ImmutableMap<XconnectKey, Integer> getNext() {
-        if (xconnectNextObjStore != null) {
-            return ImmutableMap.copyOf(xconnectNextObjStore.asJavaMap());
-        } else {
-            return ImmutableMap.of();
-        }
-    }
-
-    @Override
-    public int getNextId(DeviceId deviceId, VlanId vlanId) {
-        return Versioned.valueOrElse(xconnectNextObjStore.get(new XconnectKey(deviceId, vlanId)), -1);
-    }
-
-    @Override
-    public void removeNextId(int nextId) {
-        xconnectNextObjStore.entrySet().forEach(e -> {
-            if (e.getValue().value() == nextId) {
-                xconnectNextObjStore.remove(e.getKey());
-            }
-        });
-    }
-
-    private class XconnectMapListener implements MapEventListener<XconnectKey, Set<XconnectEndpoint>> {
-        @Override
-        public void event(MapEvent<XconnectKey, Set<XconnectEndpoint>> event) {
-            XconnectKey key = event.key();
-            Set<XconnectEndpoint> ports = Versioned.valueOrNull(event.newValue());
-            Set<XconnectEndpoint> oldPorts = Versioned.valueOrNull(event.oldValue());
-
-            switch (event.type()) {
-                case INSERT:
-                    populateXConnect(key, ports);
-                    break;
-                case UPDATE:
-                    updateXConnect(key, oldPorts, ports);
-                    break;
-                case REMOVE:
-                    revokeXConnect(key, oldPorts);
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    private class InternalDeviceListener implements DeviceListener {
-        // Offload the execution to an executor and then process the event
-        // if this instance is the leader of the device
-        @Override
-        public void event(DeviceEvent event) {
-            deviceEventExecutor.execute(() -> {
-                DeviceId deviceId = event.subject().id();
-                // Just skip if we are not the leader
-                if (!isLocalLeader(deviceId)) {
-                    log.debug("Not the leader of {}. Skip event {}", deviceId, event);
-                    return;
-                }
-                // Populate or revoke according to the device availability
-                if (deviceService.isAvailable(deviceId)) {
-                    init(deviceId);
-                } else {
-                    cleanup(deviceId);
-                }
-            });
-        }
-        // We want to manage only a subset of events and if we are the leader
-        @Override
-        public boolean isRelevant(DeviceEvent event) {
-            return event.type() == DeviceEvent.Type.DEVICE_ADDED ||
-                    event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
-                    event.type() == DeviceEvent.Type.DEVICE_UPDATED;
-        }
-    }
-
-    private class InternalHostListener implements HostListener {
-        @Override
-        public void event(HostEvent event) {
-            hostEventExecutor.execute(() -> {
-
-                switch (event.type()) {
-                    case HOST_ADDED:
-                    case HOST_REMOVED:
-                    case HOST_UPDATED:
-                        log.trace("Unhandled host event type: {} received. Ignoring.", event.type());
-                        break;
-                    case HOST_MOVED:
-                        log.trace("Processing host event {}", event);
-
-                        Host host = event.subject();
-                        Set<HostLocation> prevLocations = event.prevSubject().locations();
-                        Set<HostLocation> newLocations = host.locations();
-
-                        // Dual-home host port failure
-                        // For each old location, in failed and paired devices update L2 vlan groups
-                        Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
-
-                            Optional<DeviceId> pairDeviceId = srService.getPairDeviceId(prevLocation.deviceId());
-                            Optional<PortNumber> pairLocalPort = srService.getPairLocalPort(prevLocation.deviceId());
-
-                            if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
-                                    .anyMatch(location -> location.deviceId().equals(pairDeviceId.get())) &&
-                                    hasXconnect(new ConnectPoint(prevLocation.deviceId(), prevLocation.port()))) {
-
-                                List<VlanId> xconnectVlans = getXconnectVlans(prevLocation.deviceId(),
-                                                                              prevLocation.port());
-                                xconnectVlans.forEach(xconnectVlan -> {
-                                    // Add single-home host into L2 multicast group at paired device side.
-                                    // Also append ACL rule to forward traffic from paired port to L2 multicast group.
-                                    newLocations.stream()
-                                            .filter(location -> location.deviceId().equals(pairDeviceId.get()))
-                                            .forEach(location -> populateL2Multicast(location.deviceId(),
-                                                                                     srService.getPairLocalPort(
-                                                                                             location.deviceId()).get(),
-                                                                                     xconnectVlan,
-                                                                                     Collections.singletonList(
-                                                                                             location.port())));
-                                    // Ensure pair-port attached to xconnect vlan flooding group
-                                    // at dual home failed device.
-                                    updateL2Flooding(prevLocation.deviceId(), pairLocalPort.get(), xconnectVlan, true);
-                                });
-                            }
-                        });
-
-                        // Dual-home host port restoration
-                        // For each new location, reverse xconnect loop prevention groups.
-                        Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
-                            final Optional<DeviceId> pairDeviceId = srService.getPairDeviceId(newLocation.deviceId());
-                            Optional<PortNumber> pairLocalPort = srService.getPairLocalPort(newLocation.deviceId());
-                            if (pairDeviceId.isPresent() && pairLocalPort.isPresent() &&
-                                    hasXconnect((new ConnectPoint(newLocation.deviceId(), newLocation.port())))) {
-
-                                List<VlanId> xconnectVlans = getXconnectVlans(newLocation.deviceId(),
-                                                                              newLocation.port());
-                                xconnectVlans.forEach(xconnectVlan -> {
-                                    // Remove recovered dual homed port from vlan L2 multicast group
-                                    prevLocations.stream()
-                                            .filter(prevLocation -> prevLocation.deviceId().equals(pairDeviceId.get()))
-                                            .forEach(prevLocation -> revokeL2Multicast(
-                                                    prevLocation.deviceId(),
-                                                    xconnectVlan,
-                                                    Collections.singletonList(newLocation.port()))
-                                            );
-
-                                    // Remove pair-port from vlan's flooding group at dual home
-                                    // restored device, if needed.
-                                    if (!hasAccessPortInMulticastGroup(new VlanNextObjectiveStoreKey(
-                                            newLocation.deviceId(), xconnectVlan), pairLocalPort.get())) {
-                                        updateL2Flooding(newLocation.deviceId(),
-                                                         pairLocalPort.get(),
-                                                         xconnectVlan,
-                                                         false);
-
-                                        // Clean L2 multicast group at pair-device; also update store.
-                                        cleanupL2MulticastRule(pairDeviceId.get(),
-                                                               srService.getPairLocalPort(pairDeviceId.get()).get(),
-                                                               xconnectVlan,
-                                                               false);
-                                    }
-                                });
-                            }
-                        });
-                        break;
-
-                    default:
-                        log.warn("Unsupported host event type: {} received. Ignoring.", event.type());
-                        break;
-                }
-            });
-        }
-    }
-
-    private void init(DeviceId deviceId) {
-        getXconnects().stream()
-                .filter(desc -> desc.key().deviceId().equals(deviceId))
-                .forEach(desc -> populateXConnect(desc.key(), desc.endpoints()));
-    }
-
-    private void cleanup(DeviceId deviceId) {
-        xconnectNextObjStore.entrySet().stream()
-                .filter(entry -> entry.getKey().deviceId().equals(deviceId))
-                .forEach(entry -> xconnectNextObjStore.remove(entry.getKey()));
-        log.debug("{} is removed from xConnectNextObjStore", deviceId);
-    }
-
-    /**
-     * Populates XConnect groups and flows for given key.
-     *
-     * @param key       XConnect key
-     * @param endpoints a set of endpoints to be cross-connected
-     */
-    private void populateXConnect(XconnectKey key, Set<XconnectEndpoint> endpoints) {
-        if (!isLocalLeader(key.deviceId())) {
-            log.debug("Abort populating XConnect {}: {}", key, ERROR_NOT_LEADER);
-            return;
-        }
-
-        int nextId = populateNext(key, endpoints);
-        if (nextId == -1) {
-            log.warn("Fail to populateXConnect {}: {}", key, ERROR_NEXT_ID);
-            return;
-        }
-        populateFilter(key, endpoints);
-        populateFwd(key, nextId);
-        populateAcl(key);
-    }
-
-    /**
-     * Populates filtering objectives for given XConnect.
-     *
-     * @param key       XConnect store key
-     * @param endpoints XConnect endpoints
-     */
-    private void populateFilter(XconnectKey key, Set<XconnectEndpoint> endpoints) {
-        // FIXME Improve the logic
-        //       If port load balancer is not involved, use filtered port. Otherwise, use unfiltered port.
-        //       The purpose is to make sure existing XConnect logic can still work on a configured port.
-        boolean filtered = endpoints.stream()
-                .map(ep -> getNextTreatment(key.deviceId(), ep, false))
-                .allMatch(t -> t.type().equals(NextTreatment.Type.TREATMENT));
-
-        endpoints.stream()
-                .map(ep -> getPhysicalPorts(key.deviceId(), ep))
-                .flatMap(Set::stream).forEach(port -> {
-                    FilteringObjective.Builder filtObjBuilder = filterObjBuilder(key, port, filtered);
-                    ObjectiveContext context = new DefaultObjectiveContext(
-                            (objective) -> log.debug("XConnect FilterObj for {} on port {} populated",
-                                    key, port),
-                            (objective, error) ->
-                                    log.warn("Failed to populate XConnect FilterObj for {} on port {}: {}",
-                                            key, port, error));
-                    flowObjectiveService.filter(key.deviceId(), filtObjBuilder.add(context));
-                });
-    }
-
-    /**
-     * Populates next objectives for given XConnect.
-     *
-     * @param key       XConnect store key
-     * @param endpoints XConnect endpoints
-     * @return next id
-     */
-    private int populateNext(XconnectKey key, Set<XconnectEndpoint> endpoints) {
-        int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
-        if (nextId != -1) {
-            log.debug("NextObj for {} found, id={}", key, nextId);
-            return nextId;
-        } else {
-            NextObjective.Builder nextObjBuilder = nextObjBuilder(key, endpoints);
-            if (nextObjBuilder == null) {
-                log.warn("Fail to populate {}: {}", key, ERROR_NEXT_OBJ_BUILDER);
-                return -1;
-            }
-            ObjectiveContext nextContext = new DefaultObjectiveContext(
-                    // To serialize this with kryo
-                    (Serializable & Consumer<Objective>) (objective) ->
-                            log.debug("XConnect NextObj for {} added", key),
-                    (Serializable & BiConsumer<Objective, ObjectiveError>) (objective, error) -> {
-                        log.warn("Failed to add XConnect NextObj for {}: {}", key, error);
-                        srService.invalidateNextObj(objective.id());
-                    });
-            NextObjective nextObj = nextObjBuilder.add(nextContext);
-            flowObjectiveService.next(key.deviceId(), nextObj);
-            xconnectNextObjStore.put(key, nextObj.id());
-            log.debug("NextObj for {} not found. Creating new NextObj with id={}", key, nextObj.id());
-            return nextObj.id();
-        }
-    }
-
-    /**
-     * Populates bridging forwarding objectives for given XConnect.
-     *
-     * @param key    XConnect store key
-     * @param nextId next objective id
-     */
-    private void populateFwd(XconnectKey key, int nextId) {
-        ForwardingObjective.Builder fwdObjBuilder = fwdObjBuilder(key, nextId);
-        ObjectiveContext fwdContext = new DefaultObjectiveContext(
-                (objective) -> log.debug("XConnect FwdObj for {} populated", key),
-                (objective, error) ->
-                        log.warn("Failed to populate XConnect FwdObj for {}: {}", key, error));
-        flowObjectiveService.forward(key.deviceId(), fwdObjBuilder.add(fwdContext));
-    }
-
-    /**
-     * Populates ACL forwarding objectives for given XConnect.
-     *
-     * @param key XConnect store key
-     */
-    private void populateAcl(XconnectKey key) {
-        ForwardingObjective.Builder aclObjBuilder = aclObjBuilder(key.vlanId());
-        ObjectiveContext aclContext = new DefaultObjectiveContext(
-                (objective) -> log.debug("XConnect AclObj for {} populated", key),
-                (objective, error) ->
-                        log.warn("Failed to populate XConnect AclObj for {}: {}", key, error));
-        flowObjectiveService.forward(key.deviceId(), aclObjBuilder.add(aclContext));
-    }
-
-    /**
-     * Revokes XConnect groups and flows for given key.
-     *
-     * @param key       XConnect key
-     * @param endpoints XConnect endpoints
-     */
-    private void revokeXConnect(XconnectKey key, Set<XconnectEndpoint> endpoints) {
-        if (!isLocalLeader(key.deviceId())) {
-            log.debug("Abort revoking XConnect {}: {}", key, ERROR_NOT_LEADER);
-            return;
-        }
-
-        revokeFilter(key, endpoints);
-        int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
-        if (nextId != -1) {
-            revokeFwd(key, nextId, null);
-            revokeNext(key, endpoints, nextId, null);
-        } else {
-            log.warn("NextObj for {} does not exist in the store.", key);
-        }
-        revokeFilter(key, endpoints);
-        revokeAcl(key);
-    }
-
-    /**
-     * Revokes filtering objectives for given XConnect.
-     *
-     * @param key       XConnect store key
-     * @param endpoints XConnect endpoints
-     */
-    private void revokeFilter(XconnectKey key, Set<XconnectEndpoint> endpoints) {
-        // FIXME Improve the logic
-        //       If port load balancer is not involved, use filtered port. Otherwise, use unfiltered port.
-        //       The purpose is to make sure existing XConnect logic can still work on a configured port.
-        boolean filtered = endpoints.stream()
-                .map(ep -> getNextTreatment(key.deviceId(), ep, false))
-                .allMatch(t -> t.type().equals(NextTreatment.Type.TREATMENT));
-
-        endpoints.stream()
-                .map(ep -> getPhysicalPorts(key.deviceId(), ep)).
-                flatMap(Set::stream).forEach(port -> {
-                    FilteringObjective.Builder filtObjBuilder = filterObjBuilder(key, port, filtered);
-                    ObjectiveContext context = new DefaultObjectiveContext(
-                            (objective) -> log.debug("XConnect FilterObj for {} on port {} revoked",
-                                                     key, port),
-                            (objective, error) ->
-                                    log.warn("Failed to revoke XConnect FilterObj for {} on port {}: {}",
-                                             key, port, error));
-                    flowObjectiveService.filter(key.deviceId(), filtObjBuilder.remove(context));
-                });
-    }
-
-    /**
-     * Revokes next objectives for given XConnect.
-     *
-     * @param key        XConnect store key
-     * @param endpoints  XConnect endpoints
-     * @param nextId     next objective id
-     * @param nextFuture completable future for this next objective operation
-     */
-    private void revokeNext(XconnectKey key, Set<XconnectEndpoint> endpoints, int nextId,
-                            CompletableFuture<ObjectiveError> nextFuture) {
-        ObjectiveContext context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous NextObj for {} removed", key);
-                if (nextFuture != null) {
-                    nextFuture.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.warn("Failed to remove previous NextObj for {}: {}", key, error);
-                if (nextFuture != null) {
-                    nextFuture.complete(error);
-                }
-                srService.invalidateNextObj(objective.id());
-            }
-        };
-
-        NextObjective.Builder nextObjBuilder = nextObjBuilder(key, endpoints, nextId);
-        if (nextObjBuilder == null) {
-            log.warn("Fail to revokeNext {}: {}", key, ERROR_NEXT_OBJ_BUILDER);
-            return;
-        }
-        // Release the port load balancer if present
-        endpoints.stream()
-                .filter(endpoint -> endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER)
-                .forEach(endpoint -> {
-                    String portLoadBalancerKey = String.valueOf(((XconnectLoadBalancerEndpoint) endpoint).key());
-                    portLoadBalancerService.release(new PortLoadBalancerId(key.deviceId(),
-                            Integer.parseInt(portLoadBalancerKey)), appId);
-                });
-        flowObjectiveService.next(key.deviceId(), nextObjBuilder.remove(context));
-        xconnectNextObjStore.remove(key);
-    }
-
-    /**
-     * Revokes bridging forwarding objectives for given XConnect.
-     *
-     * @param key       XConnect store key
-     * @param nextId    next objective id
-     * @param fwdFuture completable future for this forwarding objective operation
-     */
-    private void revokeFwd(XconnectKey key, int nextId, CompletableFuture<ObjectiveError> fwdFuture) {
-        ForwardingObjective.Builder fwdObjBuilder = fwdObjBuilder(key, nextId);
-        ObjectiveContext context = new ObjectiveContext() {
-            @Override
-            public void onSuccess(Objective objective) {
-                log.debug("Previous FwdObj for {} removed", key);
-                if (fwdFuture != null) {
-                    fwdFuture.complete(null);
-                }
-            }
-
-            @Override
-            public void onError(Objective objective, ObjectiveError error) {
-                log.warn("Failed to remove previous FwdObj for {}: {}", key, error);
-                if (fwdFuture != null) {
-                    fwdFuture.complete(error);
-                }
-            }
-        };
-        flowObjectiveService.forward(key.deviceId(), fwdObjBuilder.remove(context));
-    }
-
-    /**
-     * Revokes ACL forwarding objectives for given XConnect.
-     *
-     * @param key XConnect store key
-     */
-    private void revokeAcl(XconnectKey key) {
-        ForwardingObjective.Builder aclObjBuilder = aclObjBuilder(key.vlanId());
-        ObjectiveContext aclContext = new DefaultObjectiveContext(
-                (objective) -> log.debug("XConnect AclObj for {} populated", key),
-                (objective, error) ->
-                        log.warn("Failed to populate XConnect AclObj for {}: {}", key, error));
-        flowObjectiveService.forward(key.deviceId(), aclObjBuilder.remove(aclContext));
-    }
-
-    /**
-     * Updates XConnect groups and flows for given key.
-     *
-     * @param key           XConnect key
-     * @param prevEndpoints previous XConnect endpoints
-     * @param endpoints     new XConnect endpoints
-     */
-    private void updateXConnect(XconnectKey key, Set<XconnectEndpoint> prevEndpoints,
-                                Set<XconnectEndpoint> endpoints) {
-        if (!isLocalLeader(key.deviceId())) {
-            log.debug("Abort updating XConnect {}: {}", key, ERROR_NOT_LEADER);
-            return;
-        }
-        // NOTE: ACL flow doesn't include port information. No need to update it.
-        //       Pair port is built-in and thus not going to change. No need to update it.
-
-        // remove old filter
-        prevEndpoints.stream().filter(prevEndpoint -> !endpoints.contains(prevEndpoint)).forEach(prevEndpoint ->
-                revokeFilter(key, ImmutableSet.of(prevEndpoint)));
-        // install new filter
-        endpoints.stream().filter(endpoint -> !prevEndpoints.contains(endpoint)).forEach(endpoint ->
-                populateFilter(key, ImmutableSet.of(endpoint)));
-
-        CompletableFuture<ObjectiveError> fwdFuture = new CompletableFuture<>();
-        CompletableFuture<ObjectiveError> nextFuture = new CompletableFuture<>();
-
-        int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
-        if (nextId != -1) {
-            revokeFwd(key, nextId, fwdFuture);
-
-            fwdFuture.thenAcceptAsync(fwdStatus -> {
-                if (fwdStatus == null) {
-                    log.debug("Fwd removed. Now remove group {}", key);
-                    revokeNext(key, prevEndpoints, nextId, nextFuture);
-                }
-            });
-
-            nextFuture.thenAcceptAsync(nextStatus -> {
-                if (nextStatus == null) {
-                    log.debug("Installing new group and flow for {}", key);
-                    int newNextId = populateNext(key, endpoints);
-                    if (newNextId == -1) {
-                        log.warn("Fail to updateXConnect {}: {}", key, ERROR_NEXT_ID);
-                        return;
-                    }
-                    populateFwd(key, newNextId);
-                }
-            });
-        } else {
-            log.warn("NextObj for {} does not exist in the store.", key);
-        }
-    }
-
-    /**
-     * Creates a next objective builder for XConnect with given nextId.
-     *
-     * @param key       XConnect key
-     * @param endpoints XConnect endpoints
-     * @param nextId  next objective id
-     * @return next objective builder
-     */
-    private NextObjective.Builder nextObjBuilder(XconnectKey key, Set<XconnectEndpoint> endpoints, int nextId) {
-        TrafficSelector metadata =
-                DefaultTrafficSelector.builder().matchVlanId(key.vlanId()).build();
-        NextObjective.Builder nextObjBuilder = DefaultNextObjective
-                .builder().withId(nextId)
-                .withType(NextObjective.Type.BROADCAST).fromApp(appId)
-                .withMeta(metadata);
-
-        for (XconnectEndpoint endpoint : endpoints) {
-            NextTreatment nextTreatment = getNextTreatment(key.deviceId(), endpoint, true);
-            if (nextTreatment == null) {
-                // If a PortLoadBalancer is used in the XConnect - putting on hold
-                if (endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER) {
-                    log.warn("Unable to create nextObj. PortLoadBalancer not ready");
-                    String portLoadBalancerKey = String.valueOf(((XconnectLoadBalancerEndpoint) endpoint).key());
-                    portLoadBalancerCache.asMap().putIfAbsent(new PortLoadBalancerId(key.deviceId(),
-                                    Integer.parseInt(portLoadBalancerKey)), key);
-                } else {
-                    log.warn("Unable to create nextObj. Null NextTreatment");
-                }
-                return null;
-            }
-            nextObjBuilder.addTreatment(nextTreatment);
-        }
-
-        return nextObjBuilder;
-    }
-
-    /**
-     * Creates a next objective builder for XConnect.
-     *
-     * @param key       XConnect key
-     * @param endpoints Xconnect endpoints
-     * @return next objective builder
-     */
-    private NextObjective.Builder nextObjBuilder(XconnectKey key, Set<XconnectEndpoint> endpoints) {
-        int nextId = flowObjectiveService.allocateNextId();
-        return nextObjBuilder(key, endpoints, nextId);
-    }
-
-
-    /**
-     * Creates a bridging forwarding objective builder for XConnect.
-     *
-     * @param key    XConnect key
-     * @param nextId next ID of the broadcast group for this XConnect key
-     * @return forwarding objective builder
-     */
-    private ForwardingObjective.Builder fwdObjBuilder(XconnectKey key, int nextId) {
-        /*
-         * Driver should treat objectives with MacAddress.NONE and !VlanId.NONE
-         * as the VLAN cross-connect broadcast rules
-         */
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        sbuilder.matchVlanId(key.vlanId());
-        sbuilder.matchEthDst(MacAddress.NONE);
-
-        ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
-        fob.withFlag(ForwardingObjective.Flag.SPECIFIC)
-                .withSelector(sbuilder.build())
-                .nextStep(nextId)
-                .withPriority(XCONNECT_PRIORITY)
-                .fromApp(appId)
-                .makePermanent();
-        return fob;
-    }
-
-    /**
-     * Creates an ACL forwarding objective builder for XConnect.
-     *
-     * @param vlanId cross connect VLAN id
-     * @return forwarding objective builder
-     */
-    private ForwardingObjective.Builder aclObjBuilder(VlanId vlanId) {
-        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
-        sbuilder.matchVlanId(vlanId);
-
-        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-
-        ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
-        fob.withFlag(ForwardingObjective.Flag.VERSATILE)
-                .withSelector(sbuilder.build())
-                .withTreatment(tbuilder.build())
-                .withPriority(XCONNECT_ACL_PRIORITY)
-                .fromApp(appId)
-                .makePermanent();
-        return fob;
-    }
-
-    /**
-     * Creates a filtering objective builder for XConnect.
-     *
-     * @param key  XConnect key
-     * @param port XConnect ports
-     * @param filtered true if this is a filtered port
-     * @return next objective builder
-     */
-    private FilteringObjective.Builder filterObjBuilder(XconnectKey key, PortNumber port, boolean filtered) {
-        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
-        fob.withKey(Criteria.matchInPort(port))
-                .addCondition(Criteria.matchEthDst(MacAddress.NONE))
-                .withPriority(XCONNECT_PRIORITY);
-        if (filtered) {
-            fob.addCondition(Criteria.matchVlanId(key.vlanId()));
-        } else {
-            fob.addCondition(Criteria.matchVlanId(VlanId.ANY));
-        }
-        return fob.permit().fromApp(appId);
-    }
-
-    /**
-     * Updates L2 flooding groups; add pair link into L2 flooding group of given xconnect vlan.
-     *
-     * @param deviceId Device ID
-     * @param port     Port details
-     * @param vlanId   VLAN ID
-     * @param install  Whether to add or revoke pair link addition to flooding group
-     */
-    private void updateL2Flooding(DeviceId deviceId, PortNumber port, VlanId vlanId, boolean install) {
-        XconnectKey key = new XconnectKey(deviceId, vlanId);
-        // Ensure leadership on device
-        if (!isLocalLeader(deviceId)) {
-            log.debug("Abort updating L2Flood {}: {}", key, ERROR_NOT_LEADER);
-            return;
-        }
-
-        // Locate L2 flooding group details for given xconnect vlan
-        int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
-        if (nextId == -1) {
-            log.debug("XConnect vlan {} broadcast group for device {} doesn't exists. " +
-                              "Aborting pair group linking.", vlanId, deviceId);
-            return;
-        }
-
-        // Add pairing-port group to flooding group
-        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-        // treatment.popVlan();
-        treatment.setOutput(port);
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) ->
-                        log.debug("Pair port added/removed to vlan {} next objective {} on {}",
-                                  vlanId, nextId, deviceId),
-                (objective, error) ->
-                        log.warn("Failed adding/removing pair port to vlan {} next objective {} on {}." +
-                                         "Error : {}", vlanId, nextId, deviceId, error)
-        );
-        NextObjective.Builder vlanNextObjectiveBuilder = DefaultNextObjective.builder()
-                .withId(nextId)
-                .withType(NextObjective.Type.BROADCAST)
-                .fromApp(srService.appId())
-                .withMeta(DefaultTrafficSelector.builder().matchVlanId(vlanId).build())
-                .addTreatment(treatment.build());
-        if (install) {
-            flowObjectiveService.next(deviceId, vlanNextObjectiveBuilder.addToExisting(context));
-        } else {
-            flowObjectiveService.next(deviceId, vlanNextObjectiveBuilder.removeFromExisting(context));
-        }
-        log.debug("Submitted next objective {} for vlan: {} in device {}",
-                  nextId, vlanId, deviceId);
-    }
-
-    /**
-     * Populate L2 multicast rule on given deviceId that matches given mac, given vlan and
-     * output to given port's L2 mulitcast group.
-     *
-     * @param deviceId    Device ID
-     * @param pairPort    Pair port number
-     * @param vlanId      VLAN ID
-     * @param accessPorts List of access ports to be added into L2 multicast group
-     */
-    private void populateL2Multicast(DeviceId deviceId, PortNumber pairPort,
-                                     VlanId vlanId, List<PortNumber> accessPorts) {
-        // Ensure enough rights to program pair device
-        if (!srService.shouldProgram(deviceId)) {
-            log.debug("Abort populate L2Multicast {}-{}: {}", deviceId, vlanId, ERROR_NOT_LEADER);
-            return;
-        }
-
-        boolean multicastGroupExists = true;
-        int vlanMulticastNextId;
-        VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
-        // Step 1 : Populate single homed access ports into vlan's L2 multicast group
-        NextObjective.Builder vlanMulticastNextObjBuilder = DefaultNextObjective
-                .builder()
-                .withType(NextObjective.Type.BROADCAST)
-                .fromApp(srService.appId())
-            .withMeta(DefaultTrafficSelector.builder().matchVlanId(vlanId)
-                          .matchEthDst(MacAddress.IPV4_MULTICAST).build());
-        vlanMulticastNextId = getMulticastGroupNextObjectiveId(key);
-        if (vlanMulticastNextId == -1) {
-            // Vlan's L2 multicast group doesn't exist; create it, update store and add pair port as sub-group
-            multicastGroupExists = false;
-            vlanMulticastNextId = flowObjectiveService.allocateNextId();
-            addMulticastGroupNextObjectiveId(key, vlanMulticastNextId);
-            vlanMulticastNextObjBuilder.addTreatment(
-                    DefaultTrafficTreatment.builder().setOutput(pairPort).build()
-            );
-        }
-        vlanMulticastNextObjBuilder.withId(vlanMulticastNextId);
-        int nextId = vlanMulticastNextId;
-        accessPorts.forEach(p -> {
-            TrafficTreatment.Builder egressAction = DefaultTrafficTreatment.builder();
-            // Do vlan popup action based on interface configuration
-            if (interfaceService.getInterfacesByPort(new ConnectPoint(deviceId, p))
-                    .stream().noneMatch(i -> i.vlanTagged().contains(vlanId))) {
-                egressAction.popVlan();
-            }
-            egressAction.setOutput(p);
-            vlanMulticastNextObjBuilder.addTreatment(egressAction.build());
-            addMulticastGroupPort(key, p);
-        });
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) ->
-                        log.debug("L2 multicast group installed/updated. "
-                                          + "NextObject Id {} on {} for subnet {} ",
-                                  nextId, deviceId, vlanId),
-                (objective, error) ->
-                        log.warn("L2 multicast group failed to install/update. "
-                                         + " NextObject Id {} on {} for subnet {} : {}",
-                                 nextId, deviceId, vlanId, error)
-        );
-        if (!multicastGroupExists) {
-            flowObjectiveService.next(deviceId, vlanMulticastNextObjBuilder.add(context));
-
-            // Step 2 : Populate ACL rule; selector = vlan + pair-port, output = vlan L2 multicast group
-            TrafficSelector.Builder multicastSelector = DefaultTrafficSelector.builder();
-            multicastSelector.matchEthType(Ethernet.TYPE_VLAN);
-            multicastSelector.matchInPort(pairPort);
-            multicastSelector.matchVlanId(vlanId);
-            ForwardingObjective.Builder vlanMulticastForwardingObj = DefaultForwardingObjective.builder()
-                    .withFlag(ForwardingObjective.Flag.VERSATILE)
-                    .nextStep(vlanMulticastNextId)
-                    .withSelector(multicastSelector.build())
-                    .withPriority(100)
-                    .fromApp(srService.appId())
-                    .makePermanent();
-            context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("L2 multicasting versatile rule for device {}, port/vlan {}/{} populated",
-                                             deviceId,
-                                             pairPort,
-                                             vlanId),
-                    (objective, error) -> log.warn("Failed to populate L2 multicasting versatile rule for device {}, " +
-                                                           "ports/vlan {}/{}: {}", deviceId, pairPort, vlanId, error));
-            flowObjectiveService.forward(deviceId, vlanMulticastForwardingObj.add(context));
-        } else {
-            // L2_MULTICAST & BROADCAST are similar structure in subgroups; so going with BROADCAST type.
-            vlanMulticastNextObjBuilder.withType(NextObjective.Type.BROADCAST);
-            flowObjectiveService.next(deviceId, vlanMulticastNextObjBuilder.addToExisting(context));
-        }
-    }
-
-    /**
-     * Removes access ports from VLAN L2 multicast group on given deviceId.
-     *
-     * @param deviceId    Device ID
-     * @param vlanId      VLAN ID
-     * @param accessPorts List of access ports to be added into L2 multicast group
-     */
-    private void revokeL2Multicast(DeviceId deviceId, VlanId vlanId, List<PortNumber> accessPorts) {
-        // Ensure enough rights to program pair device
-        if (!srService.shouldProgram(deviceId)) {
-            log.debug("Abort revoke L2Multicast {}-{}: {}", deviceId, vlanId, ERROR_NOT_LEADER);
-            return;
-        }
-
-        VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
-        int vlanMulticastNextId = getMulticastGroupNextObjectiveId(key);
-        if (vlanMulticastNextId == -1) {
-            return;
-        }
-        NextObjective.Builder vlanMulticastNextObjBuilder = DefaultNextObjective
-                .builder()
-                .withType(NextObjective.Type.BROADCAST)
-                .fromApp(srService.appId())
-                .withMeta(DefaultTrafficSelector.builder().matchVlanId(vlanId).build())
-                .withId(vlanMulticastNextId);
-        accessPorts.forEach(p -> {
-            TrafficTreatment.Builder egressAction = DefaultTrafficTreatment.builder();
-            // Do vlan popup action based on interface configuration
-            if (interfaceService.getInterfacesByPort(new ConnectPoint(deviceId, p))
-                    .stream().noneMatch(i -> i.vlanTagged().contains(vlanId))) {
-                egressAction.popVlan();
-            }
-            egressAction.setOutput(p);
-            vlanMulticastNextObjBuilder.addTreatment(egressAction.build());
-            removeMulticastGroupPort(key, p);
-        });
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) ->
-                        log.debug("L2 multicast group installed/updated. "
-                                          + "NextObject Id {} on {} for subnet {} ",
-                                  vlanMulticastNextId, deviceId, vlanId),
-                (objective, error) ->
-                        log.warn("L2 multicast group failed to install/update. "
-                                         + " NextObject Id {} on {} for subnet {} : {}",
-                                 vlanMulticastNextId, deviceId, vlanId, error)
-        );
-        flowObjectiveService.next(deviceId, vlanMulticastNextObjBuilder.removeFromExisting(context));
-    }
-
-    /**
-     * Cleans up VLAN L2 multicast group on given deviceId. ACL rules for the group will also be deleted.
-     * Normally multicast group is not removed if it contains access ports; which can be forced
-     * by "force" flag
-     *
-     * @param deviceId Device ID
-     * @param pairPort Pair port number
-     * @param vlanId   VLAN ID
-     * @param force    Forceful removal
-     */
-    private void cleanupL2MulticastRule(DeviceId deviceId, PortNumber pairPort, VlanId vlanId, boolean force) {
-
-        // Ensure enough rights to program pair device
-        if (!srService.shouldProgram(deviceId)) {
-            log.debug("Abort cleanup L2Multicast {}-{}: {}", deviceId, vlanId, ERROR_NOT_LEADER);
-            return;
-        }
-
-        VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
-        // Ensure L2 multicast group doesn't contain access ports
-        if (hasAccessPortInMulticastGroup(key, pairPort) && !force) {
-            return;
-        }
-
-        // Load L2 multicast group details
-        int vlanMulticastNextId = getMulticastGroupNextObjectiveId(key);
-        if (vlanMulticastNextId == -1) {
-            return;
-        }
-
-        // Step 1 : Clear ACL rule; selector = vlan + pair-port, output = vlan L2 multicast group
-        TrafficSelector.Builder l2MulticastSelector = DefaultTrafficSelector.builder();
-        l2MulticastSelector.matchEthType(Ethernet.TYPE_VLAN);
-        l2MulticastSelector.matchInPort(pairPort);
-        l2MulticastSelector.matchVlanId(vlanId);
-        ForwardingObjective.Builder vlanMulticastForwardingObj = DefaultForwardingObjective.builder()
-                .withFlag(ForwardingObjective.Flag.VERSATILE)
-                .nextStep(vlanMulticastNextId)
-                .withSelector(l2MulticastSelector.build())
-                .withPriority(100)
-                .fromApp(srService.appId())
-                .makePermanent();
-        ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) -> log.debug("L2 multicasting rule for device {}, port/vlan {}/{} deleted", deviceId,
-                                         pairPort, vlanId),
-                (objective, error) -> log.warn("Failed to delete L2 multicasting rule for device {}, " +
-                                                       "ports/vlan {}/{}: {}", deviceId, pairPort, vlanId, error));
-        flowObjectiveService.forward(deviceId, vlanMulticastForwardingObj.remove(context));
-
-        // Step 2 : Clear L2 multicast group associated with vlan
-        NextObjective.Builder l2MulticastGroupBuilder = DefaultNextObjective
-                .builder()
-                .withId(vlanMulticastNextId)
-                .withType(NextObjective.Type.BROADCAST)
-                .fromApp(srService.appId())
-            .withMeta(DefaultTrafficSelector.builder()
-                          .matchVlanId(vlanId)
-                          .matchEthDst(MacAddress.IPV4_MULTICAST).build())
-                .addTreatment(DefaultTrafficTreatment.builder().popVlan().setOutput(pairPort).build());
-        context = new DefaultObjectiveContext(
-                (objective) ->
-                        log.debug("L2 multicast group with NextObject Id {} deleted on {} for subnet {} ",
-                                  vlanMulticastNextId, deviceId, vlanId),
-                (objective, error) ->
-                        log.warn("L2 multicast group with NextObject Id {} failed to delete on {} for subnet {} : {}",
-                                 vlanMulticastNextId, deviceId, vlanId, error)
-        );
-        flowObjectiveService.next(deviceId, l2MulticastGroupBuilder.remove(context));
-
-        // Finally clear store.
-        removeMulticastGroup(key);
-    }
-
-    private int getMulticastGroupNextObjectiveId(VlanNextObjectiveStoreKey key) {
-        return Versioned.valueOrElse(xconnectMulticastNextStore.get(key), -1);
-    }
-
-    private void addMulticastGroupNextObjectiveId(VlanNextObjectiveStoreKey key, int nextId) {
-        if (nextId == -1) {
-            return;
-        }
-        xconnectMulticastNextStore.put(key, nextId);
-    }
-
-    private void addMulticastGroupPort(VlanNextObjectiveStoreKey groupKey, PortNumber port) {
-        xconnectMulticastPortsStore.compute(groupKey, (key, ports) -> {
-            if (ports == null) {
-                ports = Lists.newArrayList();
-            }
-            ports.add(port);
-            return ports;
-        });
-    }
-
-    private void removeMulticastGroupPort(VlanNextObjectiveStoreKey groupKey, PortNumber port) {
-        xconnectMulticastPortsStore.compute(groupKey, (key, ports) -> {
-            if (ports != null && !ports.isEmpty()) {
-                ports.remove(port);
-            }
-            return ports;
-        });
-    }
-
-    private void removeMulticastGroup(VlanNextObjectiveStoreKey groupKey) {
-        xconnectMulticastPortsStore.remove(groupKey);
-        xconnectMulticastNextStore.remove(groupKey);
-    }
-
-    private boolean hasAccessPortInMulticastGroup(VlanNextObjectiveStoreKey groupKey, PortNumber pairPort) {
-        List<PortNumber> ports = Versioned.valueOrElse(xconnectMulticastPortsStore.get(groupKey), ImmutableList.of());
-        return ports.stream().anyMatch(p -> !p.equals(pairPort));
-    }
-
-    // Custom-built function, when the device is not available we need a fallback mechanism
-    private boolean isLocalLeader(DeviceId deviceId) {
-        if (!mastershipService.isLocalMaster(deviceId)) {
-            // When the device is available we just check the mastership
-            if (deviceService.isAvailable(deviceId)) {
-                return false;
-            }
-            // Fallback with Leadership service - device id is used as topic
-            NodeId leader = leadershipService.runForLeadership(
-                    deviceId.toString()).leaderNodeId();
-            // Verify if this node is the leader
-            return clusterService.getLocalNode().id().equals(leader);
-        }
-        return true;
-    }
-
-    private Set<PortNumber> getPhysicalPorts(DeviceId deviceId, XconnectEndpoint endpoint) {
-        if (endpoint.type() == XconnectEndpoint.Type.PORT) {
-            PortNumber port = ((XconnectPortEndpoint) endpoint).port();
-            return Sets.newHashSet(port);
-        }
-        if (endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER) {
-            PortLoadBalancerId portLoadBalancerId = new PortLoadBalancerId(deviceId,
-                    ((XconnectLoadBalancerEndpoint) endpoint).key());
-            Set<PortNumber> ports = portLoadBalancerService.getPortLoadBalancer(portLoadBalancerId).ports();
-            return Sets.newHashSet(ports);
-        }
-        return Sets.newHashSet();
-    }
-
-    private NextTreatment getNextTreatment(DeviceId deviceId, XconnectEndpoint endpoint, boolean reserve) {
-        if (endpoint.type() == XconnectEndpoint.Type.PORT) {
-            PortNumber port = ((XconnectPortEndpoint) endpoint).port();
-            return DefaultNextTreatment.of(DefaultTrafficTreatment.builder().setOutput(port).build());
-        }
-        if (endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER) {
-            PortLoadBalancerId portLoadBalancerId = new PortLoadBalancerId(deviceId,
-                    ((XconnectLoadBalancerEndpoint) endpoint).key());
-            NextTreatment idNextTreatment =  IdNextTreatment.of(portLoadBalancerService
-                    .getPortLoadBalancerNext(portLoadBalancerId));
-            // Reserve only one time during next objective creation
-            if (reserve) {
-                if (!portLoadBalancerService.reserve(portLoadBalancerId, appId)) {
-                    log.warn("Reservation failed for {}", portLoadBalancerId);
-                    idNextTreatment = null;
-                }
-            }
-            return idNextTreatment;
-        }
-        return null;
-    }
-
-    private class InternalPortLoadBalancerListener implements PortLoadBalancerListener {
-        // Populate xconnect once portloadbalancer is available
-        @Override
-        public void event(PortLoadBalancerEvent event) {
-            portLoadBalancerExecutor.execute(() -> dequeue(event.subject().portLoadBalancerId()));
-        }
-        // When we receive INSTALLED port load balancing is ready
-        @Override
-        public boolean isRelevant(PortLoadBalancerEvent event) {
-            return event.type() == PortLoadBalancerEvent.Type.INSTALLED;
-        }
-    }
-
-    // Invalidate the cache and re-start the xconnect installation
-    private void dequeue(PortLoadBalancerId portLoadBalancerId) {
-        XconnectKey xconnectKey = portLoadBalancerCache.getIfPresent(portLoadBalancerId);
-        if (xconnectKey == null) {
-            log.trace("{} not present in the cache", portLoadBalancerId);
-            return;
-        }
-        log.debug("Dequeue {}", portLoadBalancerId);
-        portLoadBalancerCache.invalidate(portLoadBalancerId);
-        Set<XconnectEndpoint> endpoints = Versioned.valueOrNull(xconnectStore.get(xconnectKey));
-        if (endpoints == null || endpoints.isEmpty()) {
-            log.warn("Endpoints not found for XConnect {}", xconnectKey);
-            return;
-        }
-        populateXConnect(xconnectKey, endpoints);
-        log.trace("PortLoadBalancer cache size {}", portLoadBalancerCache.size());
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/package-info.java
deleted file mode 100644
index 547e3bc..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2018-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.
- */
-
-/**
- * VLAN cross connect implementation.
- */
-package org.onosproject.segmentrouting.xconnect.impl;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/AugmentedPortAuthTracker.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/AugmentedPortAuthTracker.java
deleted file mode 100644
index cc214e3..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/AugmentedPortAuthTracker.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2017-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 org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An augmented implementation of {@link PortAuthTracker}, so that we can
- * instrument its behavior for unit test assertions.
- */
-class AugmentedPortAuthTracker extends PortAuthTracker {
-
-    // instrument blocking flow activity, so we can see when we get hits
-    final List<ConnectPoint> installed = new ArrayList<>();
-    final List<ConnectPoint> cleared = new ArrayList<>();
-
-
-    void resetMetrics() {
-        installed.clear();
-        cleared.clear();
-    }
-
-    @Override
-    void installBlockingFlow(DeviceId d, PortNumber p) {
-        super.installBlockingFlow(d, p);
-        installed.add(new ConnectPoint(d, p));
-    }
-
-    @Override
-    void clearBlockingFlow(DeviceId d, PortNumber p) {
-        super.clearBlockingFlow(d, p);
-        cleared.add(new ConnectPoint(d, p));
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java
deleted file mode 100644
index a6278b2..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright 2018-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.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.DefaultControllerNode;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.TestConsistentMap;
-import org.onosproject.store.service.TestConsistentMultimap;
-
-import java.util.Optional;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.junit.Assert.*;
-
-public class DefaultRoutingHandlerTest {
-    private SegmentRoutingManager srManager;
-    private DefaultRoutingHandler dfh;
-
-    private static final DeviceId DEV1A = DeviceId.deviceId("of:1a");
-    private static final DeviceId DEV1B = DeviceId.deviceId("of:1b");
-    private static final DeviceId DEV2 = DeviceId.deviceId("of:2");
-
-    private static final NodeId NODE1 = NodeId.nodeId("192.168.1.1");
-    private static final NodeId NODE2 = NodeId.nodeId("192.168.1.2");
-    private static final NodeId NODE3 = NodeId.nodeId("192.168.1.3");
-    private static final IpAddress IP1 = IpAddress.valueOf("192.168.1.1");
-    private static final IpAddress IP2 = IpAddress.valueOf("192.168.1.2");
-    private static final IpAddress IP3 = IpAddress.valueOf("192.168.1.3");
-
-    @Before
-    public void setUp() {
-        srManager = createMock(SegmentRoutingManager.class);
-        srManager.storageService = createMock(StorageService.class);
-        expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
-        expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
-                new TestConsistentMultimap.Builder<>()).anyTimes();
-        replay(srManager.storageService);
-        srManager.routingRulePopulator = createMock(RoutingRulePopulator.class);
-        srManager.deviceService = createMock(DeviceService.class);
-        srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
-        srManager.mastershipService = createMock(MastershipService.class);
-        srManager.clusterService = createMock(ClusterService.class);
-        dfh = new DefaultRoutingHandler(srManager);
-    }
-
-    private void clearCache() {
-        dfh.invalidateShouldProgramCache(DEV1A);
-        dfh.invalidateShouldProgramCache(DEV1B);
-        dfh.invalidateShouldProgramCache(DEV2);
-    }
-
-    // Node 1 is the master of switch 1A, 1B, and 2
-    @Test
-    public void testShouldHandleRoutingCase1() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE1).anyTimes();
-        replay(srManager.mastershipService);
-
-        expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
-        replay(srManager);
-
-        // Node 1 should program every device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-        assertTrue(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 3 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-    }
-
-    // Node 1 is the master of switch 1A, 1B
-    // Node 2 is the master of switch 2
-    @Test
-    public void testShouldHandleRoutingCase2() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE2).anyTimes();
-        replay(srManager.mastershipService);
-
-        expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
-        replay(srManager);
-
-        // Node 1 should program 1A, 1B
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program 2
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertTrue(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 3 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-    }
-
-    // Node 1 is the master of switch 1A
-    // Node 2 is the master of switch 1B
-    // Node 3 is the master of switch 2
-    @Test
-    public void testShouldHandleRoutingCase3() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
-        replay(srManager.mastershipService);
-
-        expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
-        replay(srManager);
-
-        // Node 1 should program 1A, 1B
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 3 should program 2
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertTrue(dfh.shouldProgram(DEV2));
-    }
-
-    // Node 3 is the master of switch 1A, 1B, 2
-    // Later on, node 1 becomes the master of 1A; Node 2 becomes the master of 1B.
-    @Test
-    public void testShouldHandleRoutingCase4() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE3).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE3).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
-        replay(srManager.mastershipService);
-
-        expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
-        replay(srManager);
-
-        // Node 1 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 3 should program 1A, 1B and 2
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-        assertTrue(dfh.shouldProgram(DEV2));
-
-        // Mastership of switch 1A moves to Node 1
-        reset(srManager.mastershipService);
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
-        replay(srManager.mastershipService);
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 1 should program 1A, 1B
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 3 should program 2
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertTrue(dfh.shouldProgram(DEV2));
-    }
-
-    // Node 1 is the master of 1A. 1B has no master
-    // Node 2 becomes the master of 1B later
-    @Test
-    public void testShouldHandleRoutingCase5() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes();
-        replay(srManager.mastershipService);
-
-        expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
-        replay(srManager);
-
-        // Node 1 should program both 1A and 1B
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-
-        // Mastership of switch 1B moves to Node 2
-        reset(srManager.mastershipService);
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
-        replay(srManager.mastershipService);
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 1 should program 1A, 1B
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-    }
-
-    // Neither 1A or 1B has master
-    @Test
-    public void testShouldHandleRoutingCase6() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(null).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes();
-        replay(srManager.mastershipService);
-
-        expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
-        expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
-        replay(srManager);
-
-        // Node 1 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-
-        assertFalse(dfh.shouldProgram.containsKey(Sets.newHashSet(DEV1A, DEV1B)));
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
deleted file mode 100644
index d67cb07..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * Copyright 2017-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.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.PredictableExecutor;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.host.HostProbingService;
-import org.onosproject.net.host.ProbeMode;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onosproject.routeservice.RouteInfo;
-import org.onosproject.routeservice.RouteService;
-import org.onosproject.routeservice.RouteTableId;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.TestConsistentMap;
-import org.onosproject.store.service.TestConsistentMultimap;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.*;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Unit test for {@link HostHandler}.
- */
-public class HostHandlerTest {
-    private HostHandler hostHandler;
-
-    // Mocked routing and bridging tables
-    private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
-            Maps.newConcurrentMap();
-    private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
-            Maps.newConcurrentMap();
-    private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
-    // Mocked Next Id
-    private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
-
-    // Host Mac, VLAN
-    private static final ProviderId PROVIDER_ID = ProviderId.NONE;
-    private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
-    private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
-    private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
-    private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
-    private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
-    // Host IP
-    private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
-    private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
-    private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
-    private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
-    private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
-    private static final IpAddress HOST_IP33 = IpAddress.valueOf("10.0.3.3");
-    // Device
-    private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
-    private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
-    private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
-    private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
-    private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
-    private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
-    // Port
-    private static final PortNumber P1 = PortNumber.portNumber(1);
-    private static final PortNumber P2 = PortNumber.portNumber(2);
-    private static final PortNumber P3 = PortNumber.portNumber(3);
-    private static final PortNumber P9 = PortNumber.portNumber(9);
-    // Connect Point
-    private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
-    private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
-    private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
-    private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
-    private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
-    private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
-    private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
-    private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
-    private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
-    private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
-    // Connect Point for dual-homed host failover
-    private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
-    private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
-    private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
-    private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
-    private static final ConnectPoint CP33 = new ConnectPoint(DEV3, P3);
-    private static final HostLocation HOST_LOC33 = new HostLocation(CP33, 0);
-    private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
-    private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
-    private static final ConnectPoint CP42 = new ConnectPoint(DEV4, P2);
-    private static final HostLocation HOST_LOC42 = new HostLocation(CP42, 0);
-    private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
-    private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
-    // Conenct Point for mastership test
-    private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
-    private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
-    private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
-    private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
-    // Interface VLAN
-    private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
-    private static final VlanId INTF_VLAN_TAGGED_1 = VlanId.vlanId((short) 20);
-    private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(INTF_VLAN_TAGGED_1);
-    private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
-    private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
-            VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
-    private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
-    // Interface subnet
-    private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
-    private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
-    private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
-    private static final InterfaceIpAddress INTF_IP1 =
-            new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
-    private static final InterfaceIpAddress INTF_IP2 =
-            new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
-    private static final InterfaceIpAddress INTF_IP3 =
-            new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
-    // Interfaces
-    private static final Interface INTF11 =
-            new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF12 =
-            new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF13 =
-            new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
-                    null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
-    private static final Interface INTF21 =
-            new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF22 =
-            new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF31 =
-            new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF32 =
-            new Interface(null, CP32, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF33 =
-            new Interface(null, CP33, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
-                    INTF_VLAN_OTHER, null, null);
-    private static final Interface INTF39 =
-            new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    null, INTF_VLAN_PAIR, null);
-    private static final Interface INTF41 =
-            new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF42 =
-            new Interface(null, CP42, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    INTF_VLAN_UNTAGGED, null, null);
-    private static final Interface INTF49 =
-            new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                    null, INTF_VLAN_PAIR, null);
-    // Host
-    private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
-            HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
-            false);
-
-    // A set of hosts
-    private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
-    // A set of devices of which we have mastership
-    private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
-    // A set of interfaces
-    private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
-            INTF22, INTF31, INTF32, INTF33, INTF39, INTF41, INTF42, INTF49);
-
-    private MockHostProbingService mockLocationProbingService;
-
-    @Before
-    public void setUp() {
-        // Initialize pairDevice and pairLocalPort config
-        ObjectMapper mapper = new ObjectMapper();
-        ConfigApplyDelegate delegate = config -> { };
-
-        SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
-        JsonNode dev3Tree = mapper.createObjectNode();
-        dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
-        dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
-
-        SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
-        JsonNode dev4Tree = mapper.createObjectNode();
-        dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
-        dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
-
-        MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
-        mockNetworkConfigRegistry.applyConfig(dev3Config);
-        mockNetworkConfigRegistry.applyConfig(dev4Config);
-
-        // Initialize Segment Routing Manager
-        SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
-        srManager.storageService = createMock(StorageService.class);
-        expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
-        expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
-                new TestConsistentMultimap.Builder<>()).anyTimes();
-        replay(srManager.storageService);
-        srManager.cfgService = new NetworkConfigRegistryAdapter();
-        srManager.deviceConfiguration = new DeviceConfiguration(srManager);
-        srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
-        srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
-        srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
-        srManager.interfaceService = new MockInterfaceService(INTERFACES);
-        srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
-        srManager.hostService = new MockHostService(HOSTS);
-        srManager.cfgService = mockNetworkConfigRegistry;
-        mockLocationProbingService = new MockHostProbingService();
-        srManager.probingService = mockLocationProbingService;
-        srManager.linkHandler = new MockLinkHandler(srManager);
-
-        // Not important for most of the HostHandler test case. Simply return an empty set here
-        srManager.routeService = createNiceMock(RouteService.class);
-        expect(srManager.routeService.getRouteTables()).andReturn(Sets.newHashSet()).anyTimes();
-        replay(srManager.routeService);
-
-        hostHandler = new HostHandler(srManager);
-        hostHandler.hostWorkers = new PredictableExecutor(
-                0, groupedThreads("onos/sr", "h-worker-%d"), true);
-
-        ROUTING_TABLE.clear();
-        BRIDGING_TABLE.clear();
-    }
-
-    @Test
-    public void init() {
-        hostHandler.init(DEV1);
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        hostHandler.init(DEV2);
-        assertEquals(2, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testHostAddedAtWrongLocation() {
-        hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
-    }
-
-
-    @Test()
-    public void testHostAddedAtCorrectLocation() {
-        hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-    }
-
-    @Test
-    public void testHostAdded() {
-        Host subject;
-
-        // Untagged host discovered on untagged port
-        // Expect: add one routing rule and one bridging rule
-        subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Untagged host discovered on tagged/native port
-        // Expect: add one routing rule and one bridging rule
-        subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
-
-        // Tagged host discovered on untagged port
-        // Expect: ignore the host. No rule is added.
-        subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(2, BRIDGING_TABLE.size());
-
-        // Tagged host discovered on tagged port with the same IP
-        // Expect: update existing route, add one bridging rule
-        subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
-                Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
-                HOST_IP21.toIpPrefix())).vlanId);
-        assertEquals(3, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
-    }
-
-    @Test
-    public void testDualHomedHostAdded() {
-        // Add a dual-homed host that has 2 locations
-        // Expect: add two routing rules and two bridging rules
-        Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-    }
-
-    @Test
-    public void testSingleHomedHostAddedOnPairLeaf() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC33), Sets.newHashSet(HOST_IP33), false);
-
-        // Add a single-homed host with one location
-        // Expect: the pair link should not be utilized
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertEquals(P3, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP33.toIpPrefix())).portNumber);
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertEquals(P3, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
-    }
-
-    @Test
-    public void testDualHomedHostAddedOneByOne() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a dual-homed host with one location
-        // Expect: the pair link is utilized temporarily before the second location is discovered
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        // Expect probe to be sent out on pair device
-        assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, ProbeMode.DISCOVER));
-
-        // Add the second location of dual-homed host
-        // Expect: no longer use the pair link
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-    }
-
-    @Test
-    public void testHostRemoved() {
-        Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a host
-        // Expect: add one routing rule and one bridging rule
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Remove the host
-        // Expect: add the routing rule and the bridging rule
-        hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, BRIDGING_TABLE.size());
-    }
-
-    @Test
-    public void testDualHomedHostRemoved() {
-        // Add a dual-homed host that has 2 locations
-        // Expect: add two routing rules and two bridging rules
-        Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Remove a dual-homed host that has 2 locations
-        // Expect: all routing and bridging rules are removed
-        hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, BRIDGING_TABLE.size());
-    }
-
-    @Test
-    public void testHostMoved() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
-        Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a host
-        // Expect: add one new routing rule, one new bridging rule
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Move the host to CP13, which has different subnet setting
-        // Expect: remove routing rule. Change vlan in bridging rule.
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
-        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Move the host to CP21, which has same subnet setting
-        // Expect: add a new routing rule. Change vlan in bridging rule.
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-    }
-
-    @Test
-    public void testDualHomedHostMoved() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-        Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
-        Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
-        Host host5 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC12, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-
-
-        // Add a host with IP11, IP12 and LOC11, LOC21
-        // Expect: 4 routing rules and 2 bridging rules
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Move the host to LOC12, LOC21 and keep the IP
-        // Expect: 4 routing rules and 2 bridging rules all at the new location
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host5, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Move the host to LOC12, LOC22 and keep the IP
-        // Expect: 4 routing rules and 2 bridging rules all at the new location
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host5));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
-        // Expect: 4 routing rules and 2 bridging rules all at the new location
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
-        // Expect: 4 routing rules and 2 bridging rules all at the new location
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-    }
-
-    @Test
-    public void testDualHomedHostMoveTransient() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-
-        // Mock DefaultRoutingHandler
-        DefaultRoutingHandler mockDefaultRoutingHandler = createMock(DefaultRoutingHandler.class);
-        hostHandler.srManager.defaultRoutingHandler = mockDefaultRoutingHandler;
-
-        // Host moved from [1A/1, 1B/1] to [1A/2, 1B/1]
-        // We should expect only one bridging flow and one routing flow programmed on 1A
-
-        expect(mockDefaultRoutingHandler.populateBridging(DEV3, P2, HOST_MAC, HOST_VLAN_UNTAGGED))
-                .andReturn(CompletableFuture.completedFuture(null)).once();
-        expect(mockDefaultRoutingHandler.populateRoute(DEV3, HOST_IP11.toIpPrefix(),
-                HOST_MAC, HOST_VLAN_UNTAGGED, P2, true))
-                .andReturn(CompletableFuture.completedFuture(null)).once();
-        replay(mockDefaultRoutingHandler);
-
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        verify(mockDefaultRoutingHandler);
-    }
-
-    @Test
-    public void testHostMoveToInvalidLocation() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a host
-        // Expect: add one new routing rule, one new bridging rule
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Move the host to an invalid location
-        // Expect: Old flow is removed. New flow is not created
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, BRIDGING_TABLE.size());
-
-        // Move the host to a valid location
-        // Expect: add one new routing rule, one new bridging rule
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-    }
-
-    @Test
-    public void testDualHomedHostMoveToInvalidLocation() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
-        Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a host
-        // Expect: add two new routing rules, two new bridging rules
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Move first host location to an invalid location
-        // Expect: One routing and one bridging flow
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Move second host location to an invalid location
-        // Expect: No routing or bridging rule
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, BRIDGING_TABLE.size());
-
-        // Move second host location back to a valid location
-        // Expect: One routing and one bridging flow
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Move first host location back to a valid location
-        // Expect: Two routing and two bridging flow
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-    }
-
-    @Test
-    public void testDualHomingSingleLocationFail() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-
-        // Add a host
-        // Expect: add four new routing rules, two new bridging rules
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Host becomes single-homed
-        // Expect: redirect flows from host location to pair link
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Host becomes dual-homed again
-        // Expect: Redirect flows from pair link back to host location
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-    }
-
-    @Test
-    public void testDualHomingBothLocationFail() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-
-        // Add a host
-        // Expect: add four new routing rules, two new bridging rules
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Host becomes single-homed
-        // Expect: redirect flows from host location to pair link
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Host loses both locations
-        // Expect: Remove last location and all previous redirection flows
-        hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, BRIDGING_TABLE.size());
-    }
-
-    @Test
-    public void testHostUpdated() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
-        Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
-
-        // Add a host
-        // Expect: add one new routing rule. Add one new bridging rule.
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
-                INTF_VLAN_UNTAGGED)));
-
-        // Update the host IP to same subnet
-        // Expect: update routing rule with new IP. No change to bridging rule.
-        hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Update the host IP to different subnet
-        // Expect: Remove routing rule. No change to bridging rule.
-        hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-    }
-
-    @Test
-    public void testDelayedIpAndLocation() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
-        Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a dual-home host with only one location and no IP
-        // Expect: only bridging redirection works
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Discover IP
-        // Expect: routing redirection should also work
-        hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        // Expect probe to be sent out on pair device
-        assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
-
-        // Discover location
-        // Expect: cancel all redirections
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-    }
-
-    @Test
-    public void testDelayedIpAndLocation2() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
-        Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a dual-home host with only one location and no IP
-        // Expect: only bridging redirection works
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Discover Location
-        // Expect: cancel bridging redirections
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
-        // Discover IP
-        // Expect: add IP rules to both location
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-    }
-
-    @Test
-    public void testDualHomedHostUpdated() {
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
-        Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
-
-        // Add a dual-homed host with two locations and two IPs
-        // Expect: add four new routing rules. Add two new bridging rules
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Update both host IPs
-        // Expect: update routing rules with new IP. No change to bridging rule.
-        hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
-        assertEquals(4, ROUTING_TABLE.size());
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        // Update one of the host IP to different subnet
-        // Expect: update routing rule with new IP. No change to bridging rule.
-        hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
-        assertEquals(2, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
-        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
-        assertEquals(2, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-    }
-
-    @Test
-    public void testVlanForPairPort() {
-        assertEquals(INTF_VLAN_UNTAGGED, hostHandler.vlanForPairPort(VlanId.NONE, CP11));
-        assertEquals(INTF_VLAN_NATIVE, hostHandler.vlanForPairPort(VlanId.NONE, CP13));
-        assertEquals(INTF_VLAN_TAGGED_1, hostHandler.vlanForPairPort(INTF_VLAN_TAGGED_1, CP13));
-        assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP11));
-        assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP13));
-        assertNull(hostHandler.vlanForPairPort(VlanId.NONE, CP51));
-        assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP51));
-    }
-
-    @Test
-    public void testHostRemovedWithRouteRemoved() {
-        Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-
-        // Add a host
-        // Expect: add one routing rule and one bridging rule
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(1, ROUTING_TABLE.size());
-        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, BRIDGING_TABLE.size());
-        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
-        IpPrefix prefix = IpPrefix.valueOf("55.55.55.0/24");
-
-        // Setting up mock route service
-        RouteService routeService = hostHandler.srManager.routeService;
-        reset(routeService);
-
-        IpAddress nextHopIp2 = IpAddress.valueOf("20.0.0.1");
-        MacAddress nextHopMac2 = MacAddress.valueOf("00:22:33:44:55:66");
-        VlanId nextHopVlan2 = VlanId.NONE;
-
-        Route r1 = new Route(Route.Source.STATIC, prefix, HOST_IP11);
-        ResolvedRoute rr1 = new ResolvedRoute(r1, HOST_MAC, VlanId.NONE);
-        Route r2 = new Route(Route.Source.STATIC, prefix, nextHopIp2);
-        ResolvedRoute rr2 = new ResolvedRoute(r2, nextHopMac2, nextHopVlan2);
-        RouteInfo routeInfo = new RouteInfo(prefix, rr1, Sets.newHashSet(rr1, rr2));
-        RouteTableId routeTableId = new RouteTableId("ipv4");
-
-        expect(routeService.getRouteTables()).andReturn(Sets.newHashSet(routeTableId));
-        expect(routeService.getRoutes(routeTableId)).andReturn(Sets.newHashSet(routeInfo));
-        replay(routeService);
-
-        // Setting up mock device configuration
-        hostHandler.srManager.deviceConfiguration = EasyMock.createNiceMock(DeviceConfiguration.class);
-        DeviceConfiguration deviceConfiguration = hostHandler.srManager.deviceConfiguration;
-        expect(deviceConfiguration.inSameSubnet(CP11, HOST_IP11)).andReturn(true);
-        deviceConfiguration.removeSubnet(CP11, prefix);
-        expectLastCall();
-        replay(deviceConfiguration);
-
-        // Remove the host
-        // Expect: add the routing rule and the bridging rule
-        hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, BRIDGING_TABLE.size());
-
-        // Expect: subnet is removed from device config
-        verify(deviceConfiguration);
-    }
-
-    @Test
-    public void testHostProbing() {
-        // Case: [1A/1, 1B/1] -> [1A/2, 1B/1]
-        // Expect: DISCOVER probe should be sent to every port on 1B that has the same VLAN as 1A/2
-        //         VERIFY probe should be sent to 1B/1
-        Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-        Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
-                Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-        hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-
-        hostHandler.srManager.probingService = createMock(HostProbingService.class);
-        hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.DISCOVER);
-        expectLastCall();
-        hostHandler.srManager.probingService.probeHost(host2, CP42, ProbeMode.DISCOVER);
-        expectLastCall();
-        hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.VERIFY);
-        expectLastCall();
-        replay(hostHandler.srManager.probingService);
-
-        hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-
-        verify(hostHandler.srManager.probingService);
-    }
-
-    @Test
-    public void testEffectiveLocations() {
-        Host regularHost = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_TAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC12), Sets.newHashSet(HOST_IP11), false);
-        Host auxHost = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_TAGGED,
-                Sets.newHashSet(HOST_LOC11, HOST_LOC12), Sets.newHashSet(HOST_LOC21, HOST_LOC22),
-                Sets.newHashSet(HOST_IP11), VlanId.NONE, EthType.EtherType.UNKNOWN.ethType(), false, false);
-
-        assertEquals(Sets.newHashSet(HOST_LOC11, HOST_LOC12), hostHandler.effectiveLocations(regularHost));
-        assertEquals(Sets.newHashSet(HOST_LOC21, HOST_LOC22), hostHandler.effectiveLocations(auxHost));
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java
deleted file mode 100644
index 68472de..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * Copyright 2019-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.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.MPLS;
-import org.onosproject.TestApplicationId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-
-import java.util.Collections;
-
-import static org.easymock.EasyMock.*;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
-import static org.onlab.packet.ICMP.*;
-import static org.onlab.packet.ICMP6.ECHO_REPLY;
-import static org.onosproject.segmentrouting.TestUtils.*;
-
-/**
- * Tests for IcmpHandler.
- */
-public class IcmpHandlerTest {
-
-    private IcmpHandler icmpHandler;
-    private MockPacketService packetService;
-    private SegmentRoutingManager segmentRoutingManager;
-    private ApplicationId testApplicationId = TestApplicationId.create("test");
-
-    @Before
-    public void setUp() {
-
-        // Init
-        ObjectMapper mapper = new ObjectMapper();
-        ConfigApplyDelegate delegate = config -> { };
-
-        // Setup configuration for app
-        SegmentRoutingAppConfig appConfig = new SegmentRoutingAppConfig();
-        JsonNode appTree = mapper.createObjectNode();
-        appConfig.init(testApplicationId, "icmp-handler-test", appTree, mapper, delegate);
-        appConfig.setSuppressSubnet(Collections.emptySet());
-
-        // Setup configuration for the devices
-        SegmentRoutingDeviceConfig remoteLeafConfig = new SegmentRoutingDeviceConfig();
-        JsonNode remoteLeafTree = mapper.createObjectNode();
-        remoteLeafConfig.init(REMOTE_LEAF, "icmp-handler-test", remoteLeafTree, mapper, delegate);
-        remoteLeafConfig.setNodeSidIPv4(REMOTE_LEAF_SID4)
-                .setNodeSidIPv6(REMOTE_LEAF_SID6)
-                .setRouterIpv4(REMOTE_LEAF_LB4)
-                .setRouterIpv6(REMOTE_LEAF_LB6)
-                .setIsEdgeRouter(true)
-                .setRouterMac(REMOTE_MAC.toString());
-        SegmentRoutingDeviceConfig localLeafConfig = new SegmentRoutingDeviceConfig();
-        JsonNode localLeafTree = mapper.createObjectNode();
-        localLeafConfig.init(LOCAL_LEAF, "icmp-handler-test", localLeafTree, mapper, delegate);
-        localLeafConfig.setNodeSidIPv4(LOCAL_LEAF_SID4)
-                .setRouterIpv4(LOCAL_LEAF_LB4)
-                .setNodeSidIPv6(LOCAL_LEAF_SID6)
-                .setRouterIpv6(LOCAL_LEAF_LB6)
-                .setIsEdgeRouter(true)
-                .setRouterMac(LOCAL_MAC.toString());
-        SegmentRoutingDeviceConfig localLeaf1Config = new SegmentRoutingDeviceConfig();
-        JsonNode localLeaf1Tree = mapper.createObjectNode();
-        localLeaf1Config.init(LOCAL_LEAF1, "icmp-handler-test", localLeaf1Tree, mapper, delegate);
-        localLeaf1Config.setNodeSidIPv4(LOCAL_LEAF1_SID4)
-                .setRouterIpv4(LOCAL_LEAF1_LB4)
-                .setNodeSidIPv6(LOCAL_LEAF1_SID6)
-                .setRouterIpv6(LOCAL_LEAF1_LB6)
-                .setIsEdgeRouter(true)
-                .setRouterMac(LOCAL_MAC1.toString())
-                .setPairDeviceId(LOCAL_LEAF2)
-                .setPairLocalPort(P3);
-        SegmentRoutingDeviceConfig localLeaf2Config = new SegmentRoutingDeviceConfig();
-        JsonNode localLeaf2Tree = mapper.createObjectNode();
-        localLeaf2Config.init(LOCAL_LEAF2, "icmp-handler-test", localLeaf2Tree, mapper, delegate);
-        localLeaf2Config.setNodeSidIPv4(LOCAL_LEAF2_SID4)
-                .setRouterIpv4(LOCAL_LEAF2_LB4)
-                .setNodeSidIPv6(LOCAL_LEAF2_SID6)
-                .setRouterIpv6(LOCAL_LEAF2_LB6)
-                .setIsEdgeRouter(true)
-                .setRouterMac(LOCAL_MAC2.toString())
-                .setPairDeviceId(LOCAL_LEAF1)
-                .setPairLocalPort(P3);
-
-        // Setup configuration for ports
-        InterfaceConfig remoteLeafPorts1Config = new InterfaceConfig();
-        ArrayNode remoteLeafPorts1Tree = mapper.createArrayNode();
-        remoteLeafPorts1Config.init(CP12, "icmp-handler-test", remoteLeafPorts1Tree, mapper, delegate);
-        remoteLeafPorts1Config.addInterface(INTF1);
-        InterfaceConfig remoteLeafPorts2Config = new InterfaceConfig();
-        ArrayNode remoteLeafPorts2Tree = mapper.createArrayNode();
-        remoteLeafPorts2Config.init(CP13, "icmp-handler-test", remoteLeafPorts2Tree, mapper, delegate);
-        remoteLeafPorts2Config.addInterface(INTF2);
-        InterfaceConfig localLeafPortsConfig = new InterfaceConfig();
-        ArrayNode localLeafPortsTree = mapper.createArrayNode();
-        localLeafPortsConfig.init(CP1011, "icmp-handler-test", localLeafPortsTree, mapper, delegate);
-        localLeafPortsConfig.addInterface(INTF111);
-        InterfaceConfig localLeaf1PortsConfig = new InterfaceConfig();
-        ArrayNode localLeaf1PortsTree = mapper.createArrayNode();
-        localLeaf1PortsConfig.init(CP2011, "icmp-handler-test", localLeaf1PortsTree, mapper, delegate);
-        localLeaf1PortsConfig.addInterface(INTF211);
-        InterfaceConfig localLeaf2Ports1Config = new InterfaceConfig();
-        ArrayNode localLeaf2Ports1Tree = mapper.createArrayNode();
-        localLeaf2Ports1Config.init(CP2021, "icmp-handler-test", localLeaf2Ports1Tree, mapper, delegate);
-        localLeaf2Ports1Config.addInterface(INTF212);
-        InterfaceConfig localLeaf2Ports2Config = new InterfaceConfig();
-        ArrayNode localLeaf2Ports2Tree = mapper.createArrayNode();
-        localLeaf2Ports2Config.init(CP2024, "icmp-handler-test", localLeaf2Ports2Tree, mapper, delegate);
-        localLeaf2Ports2Config.addInterface(INTF213);
-
-        // Apply config
-        MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
-
-        mockNetworkConfigRegistry.applyConfig(remoteLeafConfig);
-        mockNetworkConfigRegistry.applyConfig(remoteLeafPorts1Config);
-        mockNetworkConfigRegistry.applyConfig(remoteLeafPorts2Config);
-        mockNetworkConfigRegistry.applyConfig(localLeafConfig);
-        mockNetworkConfigRegistry.applyConfig(localLeafPortsConfig);
-        mockNetworkConfigRegistry.applyConfig(localLeaf1Config);
-        mockNetworkConfigRegistry.applyConfig(localLeaf1PortsConfig);
-        mockNetworkConfigRegistry.applyConfig(localLeaf2Config);
-        mockNetworkConfigRegistry.applyConfig(localLeaf2Ports1Config);
-        mockNetworkConfigRegistry.applyConfig(localLeaf2Ports2Config);
-
-        segmentRoutingManager = new SegmentRoutingManager();
-        segmentRoutingManager.appId = testApplicationId;
-        packetService = new MockPacketService();
-        segmentRoutingManager.packetService = packetService;
-        segmentRoutingManager.cfgService = mockNetworkConfigRegistry;
-        segmentRoutingManager.neighbourResolutionService = new MockNeighbourResolutionService();
-        segmentRoutingManager.interfaceService = new MockInterfaceService(ImmutableSet.of(
-                INTF1, INTF2, INTF111, INTF211, INTF212, INTF213));
-        segmentRoutingManager.deviceConfiguration = new DeviceConfiguration(segmentRoutingManager);
-        segmentRoutingManager.ipHandler = new IpHandler(segmentRoutingManager);
-        segmentRoutingManager.deviceService = createMock(DeviceService.class);
-        segmentRoutingManager.routeService = new MockRouteService(ROUTE_STORE);
-        segmentRoutingManager.hostService = new MockHostService(Collections.emptySet());
-        icmpHandler = new IcmpHandler(segmentRoutingManager);
-    }
-
-    // Ping to our gateway
-    @Test
-    public void testPing4MyGateway() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_MY, CP12);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_MY.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_MY.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_MY.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to our gateway
-    @Test
-    public void testPing6MyGateway() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_MY, CP12);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_MY.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_MY.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_MY.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping to a gateway attached to our leaf
-    @Test
-    public void testPing4LocalGateway() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_LOCAL, CP12);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOCAL.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOCAL.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOCAL.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOCAL.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to a gateway attached to our leaf
-    @Test
-    public void testPing6LocalGateway() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOCAL, CP12);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOCAL.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOCAL.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOCAL.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOCAL.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping to a gateway attached only to the pair leaf (routing through spine)
-    @Test
-    public void testPing4RemoteGatewaySamePair() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_SAME, CP2025);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_SAME.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_SAME.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_SAME.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof MPLS);
-        MPLS mpls = (MPLS) ethernet.getPayload();
-        assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID4));
-        assertTrue(mpls.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) mpls.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4_SAME.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to a gateway attached only to the pair leaf (routing through spine)
-    @Test
-    public void testPing6RemoteGatewaySamePair() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_SAME, CP2025);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_SAME.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_SAME.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_SAME.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof MPLS);
-        MPLS mpls = (MPLS) ethernet.getPayload();
-        assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID6));
-        assertTrue(mpls.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) mpls.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_SAME.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping to a gateway but destination leaf is down
-    @Test
-    public void testPing4RemoteGatewayLeafDown() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF))
-                .andReturn(false)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4, CP11);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4.getSourceMAC());
-        assertNull(ethernet);
-
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to a gateway but destination leaf is down
-    @Test
-    public void testPing6RemoteGatewayLeafDown() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF))
-                .andReturn(false)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6, CP11);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6.getSourceMAC());
-        assertNull(ethernet);
-
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping to a gateway but one of the destination leaf is down
-    @Test
-    public void testPing4RemoteGatewayLeaf1Down() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(false)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV41, CP11);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV41.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV41.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV41.getSourceMAC()));
-        assertThat(ethernet.getEtherType(), is(Ethernet.MPLS_UNICAST));
-        assertTrue(ethernet.getPayload() instanceof MPLS);
-        MPLS mpls = (MPLS) ethernet.getPayload();
-        assertThat(mpls.getLabel(), is(LOCAL_LEAF2_SID4));
-        assertTrue(mpls.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) mpls.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to a gateway but one of the destination leaf is down
-    @Test
-    public void testPing6RemoteGatewayLeaf2Down() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(false)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV61, CP11);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV61.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV61.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV61.getSourceMAC()));
-        assertThat(ethernet.getEtherType(), is(Ethernet.MPLS_UNICAST));
-        assertTrue(ethernet.getPayload() instanceof MPLS);
-        MPLS mpls = (MPLS) ethernet.getPayload();
-        assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID6));
-        assertTrue(mpls.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) mpls.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to a link local address
-    @Test
-    public void testPing6LinkLocalAddress() {
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LL, CP12);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LL.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LL.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LL.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_LL.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_LL.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-    }
-
-    // Ping to the looback of our leaf
-    @Test
-    public void testPing4Loopback() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK, CP12);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to the looback of our leaf
-    @Test
-    public void testPing6Loopback() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK, CP12);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping to the looback of our leaf (pair)
-    @Test
-    public void testPing4LoopbackPair() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2011);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to the looback of our leaf (pair)
-    @Test
-    public void testPing6LoopbackPair() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2021);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping to the loopback of the leaf but hashing of the bond interfaces sends to wrong leaf
-    @Test
-    public void testPing4LoopbackPairDifferentLeaf() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2021);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to the loopback of the leaf but hashing of the bond interfaces sends to wrong leaf
-    @Test
-    public void testPing6LoopbackPairDifferentLeaf() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2011);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping loopback of a destination that is down but
-    // hashing of the bond interfaces sends to other leaf
-    @Test
-    public void testPing4LoopbackPairDifferentLeafDown() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(false)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2021);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 loopback of a destination that is down but
-    // hashing of the bond interfaces sends to other leaf
-    @Test
-    public void testPing6LoopbackPairDifferentLeafDown() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(false)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2011);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping to a dh gateway
-    @Test
-    public void testPing4GatewayPair() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmp(ETH_REQ_IPV4_GATEWAY_PAIR, CP2011);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_GATEWAY_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_GATEWAY_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_GATEWAY_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv4);
-        IPv4 ip = (IPv4) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV4_GATEWAY_PAIR.toInt()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
-        assertTrue(ip.getPayload() instanceof ICMP);
-        ICMP icmp = (ICMP) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
-        assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-    // Ping6 to a dh gateway
-    @Test
-    public void testPing6GatewayPair() {
-        // Expected behavior
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
-                .andReturn(true)
-                .times(1);
-        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
-                .andReturn(true)
-                .times(1);
-        replay(segmentRoutingManager.deviceService);
-
-        // Process
-        icmpHandler.processIcmpv6(ETH_REQ_IPV6_GATEWAY_PAIR, CP2021);
-
-        // Verify packet-out
-        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_GATEWAY_PAIR.getSourceMAC());
-        assertNotNull(ethernet);
-        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_GATEWAY_PAIR.getDestinationMAC()));
-        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_GATEWAY_PAIR.getSourceMAC()));
-        assertTrue(ethernet.getPayload() instanceof IPv6);
-        IPv6 ip = (IPv6) ethernet.getPayload();
-        assertThat(ip.getSourceAddress(), is(DST_IPV6_GATEWAY_PAIR.toOctets()));
-        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
-        assertTrue(ip.getPayload() instanceof ICMP6);
-        ICMP6 icmp = (ICMP6) ip.getPayload();
-        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
-        // Verify behavior
-        verify(segmentRoutingManager.deviceService);
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java
deleted file mode 100644
index a90b1cf..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2017-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 org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Mock Bridging Table Key.
- */
-class MockBridgingTableKey {
-    DeviceId deviceId;
-    MacAddress macAddress;
-    VlanId vlanId;
-
-    MockBridgingTableKey(DeviceId deviceId, MacAddress macAddress, VlanId vlanId) {
-        this.deviceId = deviceId;
-        this.macAddress = macAddress;
-        this.vlanId = vlanId;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof MockBridgingTableKey)) {
-            return false;
-        }
-        final MockBridgingTableKey other = (MockBridgingTableKey) obj;
-        return Objects.equals(this.macAddress, other.macAddress) &&
-                Objects.equals(this.deviceId, other.deviceId) &&
-                Objects.equals(this.vlanId, other.vlanId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(macAddress, vlanId);
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java
deleted file mode 100644
index 68b0db8..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2017-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 org.onosproject.net.PortNumber;
-
-import java.util.Objects;
-
-/**
- * Mock Bridging Table Value.
- */
-class MockBridgingTableValue {
-    boolean popVlan;
-    PortNumber portNumber;
-
-    MockBridgingTableValue(boolean popVlan, PortNumber portNumber) {
-        this.popVlan = popVlan;
-        this.portNumber = portNumber;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof MockBridgingTableValue)) {
-            return false;
-        }
-        final MockBridgingTableValue other = (MockBridgingTableValue) obj;
-        return Objects.equals(this.popVlan, other.popVlan) &&
-                Objects.equals(this.portNumber, other.portNumber);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(popVlan, portNumber);
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
deleted file mode 100644
index 0002948..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2017-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 org.onlab.packet.IpPrefix;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Mock Default Routing Handler.
- */
-public class MockDefaultRoutingHandler extends DefaultRoutingHandler {
-    private Map<ConnectPoint, Set<IpPrefix>> subnetTable;
-    private Map<MockRoutingTableKey, MockRoutingTableValue> routingTable;
-
-    MockDefaultRoutingHandler(SegmentRoutingManager srManager,
-                              Map<ConnectPoint, Set<IpPrefix>> subnetTable,
-                              Map<MockRoutingTableKey, MockRoutingTableValue> routingTable) {
-        super(srManager);
-        this.subnetTable = subnetTable;
-        this.routingTable = routingTable;
-    }
-
-    @Override
-    protected void populateSubnet(Set<ConnectPoint> cpts, Set<IpPrefix> subnets) {
-        subnetTable.forEach((k, v) -> {
-            if (!cpts.contains(k)) {
-                subnetTable.get(k).removeAll(subnets);
-                if (subnetTable.get(k).isEmpty()) {
-                    subnetTable.remove(k);
-                }
-            }
-        });
-
-        cpts.forEach(cpt -> subnetTable.put(cpt, subnets));
-    }
-
-    @Override
-    protected boolean revokeSubnet(Set<IpPrefix> subnets) {
-        for (Map.Entry<ConnectPoint, Set<IpPrefix>> entry : subnetTable.entrySet()) {
-            entry.getValue().removeAll(subnets);
-            if (entry.getValue().isEmpty()) {
-                subnetTable.remove(entry.getKey());
-            }
-        }
-        routingTable.entrySet().removeIf(e -> subnets.contains(e.getKey().ipPrefix));
-        return true;
-    }
-
-    @Override
-    protected boolean shouldProgram(DeviceId deviceId) {
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDevice.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDevice.java
deleted file mode 100644
index 0abbf2a..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDevice.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2016-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 org.onosproject.net.Annotations;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.DeviceId;
-/**
- * Test fixture for the device service.
- */
-public class MockDevice extends DefaultDevice {
-
-        public MockDevice(DeviceId id, Annotations annotations) {
-            super(null, id, null, null, null, null, null, null, annotations);
-        }
- }
-
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDeviceService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDeviceService.java
deleted file mode 100644
index 1d173f6..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDeviceService.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2016-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 java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Port;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceServiceAdapter;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-
-/**
- * Test fixture for the device service.
- */
-public class MockDeviceService extends DeviceServiceAdapter {
-    private List<Device> devices = new LinkedList<>();
-    private DeviceListener listener;
-
-    public void addDevice(Device dev) {
-        devices.add(dev);
-    }
-
-    public void addMultipleDevices(Set<Device> devicesToAdd) {
-        devicesToAdd.forEach(dev -> devices.add(dev));
-    }
-
-    @Override
-    public Device getDevice(DeviceId deviceId) {
-        for (Device dev : devices) {
-            if (dev.id().equals(deviceId)) {
-                return dev;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Port getPort(ConnectPoint cp) {
-        return new DefaultPort(null, null, false);
-    }
-
-    @Override
-    public Iterable<Device> getAvailableDevices() {
-        return devices;
-    }
-
-    @Override
-    public void addListener(DeviceListener listener) {
-        this.listener = listener;
-    }
-
-    /**
-     * Get the listener.
-     */
-    public DeviceListener getListener() {
-        return listener;
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java
deleted file mode 100644
index 0f2d7a9..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2017-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 org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-
-import java.util.Map;
-
-/**
- * Mock Flow Objective Service.
- */
-public class MockFlowObjectiveService extends FlowObjectiveServiceAdapter {
-    private Map<MockBridgingTableKey, MockBridgingTableValue> bridgingTable;
-    private Map<Integer, TrafficTreatment> nextTable;
-
-    MockFlowObjectiveService(Map<MockBridgingTableKey, MockBridgingTableValue> bridgingTable,
-                             Map<Integer, TrafficTreatment> nextTable) {
-        this.bridgingTable = bridgingTable;
-        this.nextTable = nextTable;
-    }
-
-    @Override
-    public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
-        TrafficSelector selector = forwardingObjective.selector();
-        TrafficTreatment treatment = nextTable.get(forwardingObjective.nextId());
-        MacAddress macAddress = ((EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST)).mac();
-        VlanId vlanId = ((VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID)).vlanId();
-
-        boolean popVlan = treatment.allInstructions().stream()
-                .filter(instruction -> instruction.type().equals(Instruction.Type.L2MODIFICATION))
-                .anyMatch(instruction -> ((L2ModificationInstruction) instruction).subtype()
-                        .equals(L2ModificationInstruction.L2SubType.VLAN_POP));
-        PortNumber portNumber = treatment.allInstructions().stream()
-                .filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT))
-                .map(instruction -> ((Instructions.OutputInstruction) instruction).port()).findFirst().orElse(null);
-        if (portNumber == null) {
-            throw new IllegalArgumentException();
-        }
-
-        Objective.Operation op = forwardingObjective.op();
-
-        MockBridgingTableKey btKey = new MockBridgingTableKey(deviceId, macAddress, vlanId);
-        MockBridgingTableValue btValue = new MockBridgingTableValue(popVlan, portNumber);
-
-        if (op.equals(Objective.Operation.ADD)) {
-            bridgingTable.put(btKey, btValue);
-            forwardingObjective.context().ifPresent(context -> context.onSuccess(forwardingObjective));
-        } else if (op.equals(Objective.Operation.REMOVE)) {
-            bridgingTable.remove(btKey, btValue);
-            forwardingObjective.context().ifPresent(context -> context.onSuccess(forwardingObjective));
-        } else {
-            forwardingObjective.context().ifPresent(context ->
-                    context.onError(forwardingObjective, ObjectiveError.UNKNOWN));
-            throw new IllegalArgumentException();
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostProbingService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostProbingService.java
deleted file mode 100644
index 807db0c..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostProbingService.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2017-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.Lists;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-import org.onosproject.net.host.HostProbingService;
-import org.onosproject.net.host.ProbeMode;
-
-import java.util.List;
-import java.util.Objects;
-
-public class MockHostProbingService implements HostProbingService {
-    List<Probe> probes;
-
-    private class Probe {
-        private Host host;
-        private ConnectPoint connectPoint;
-        private ProbeMode probeMode;
-
-        Probe(Host host, ConnectPoint connectPoint, ProbeMode probeMode) {
-            this.host = host;
-            this.connectPoint = connectPoint;
-            this.probeMode = probeMode;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (!(o instanceof Probe)) {
-                return false;
-            }
-            Probe that = (Probe) o;
-            return (Objects.equals(this.host, that.host) &&
-                    Objects.equals(this.connectPoint, that.connectPoint) &&
-                    Objects.equals(this.probeMode, that.probeMode));
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(host, connectPoint, probeMode);
-        }
-    }
-
-    MockHostProbingService() {
-        probes = Lists.newArrayList();
-    }
-
-    boolean verifyProbe(Host host, ConnectPoint connectPoint, ProbeMode probeMode) {
-        Probe probe = new Probe(host, connectPoint, probeMode);
-        return probes.contains(probe);
-    }
-
-    @Override
-    public void probeHost(Host host, ConnectPoint connectPoint, ProbeMode probeMode) {
-        probes.add(new Probe(host, connectPoint, probeMode));
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostService.java
deleted file mode 100644
index e8c4701..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostService.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2017-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.ImmutableSet;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.host.HostServiceAdapter;
-
-import java.util.Set;
-
-/**
- * Mock Host Service.
- */
-public class MockHostService extends HostServiceAdapter {
-    private Set<Host> hosts;
-
-    MockHostService(Set<Host> hosts) {
-        this.hosts = ImmutableSet.copyOf(hosts);
-    }
-
-    @Override
-    public Set<Host> getHosts() {
-        return hosts;
-    }
-
-    @Override
-    public Host getHost(HostId hostId) {
-        return hosts.stream().filter(host -> hostId.equals(host.id())).findFirst().orElse(null);
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java
deleted file mode 100644
index 6e170b0..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2017-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.ImmutableSet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.impl.InterfaceManager;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.util.stream.Collectors.toSet;
-
-/**
- * Mock Interface Service.
- */
-public class MockInterfaceService extends InterfaceManager {
-    private Set<Interface> interfaces;
-
-    MockInterfaceService(Set<Interface> interfaces) {
-        this.interfaces = ImmutableSet.copyOf(interfaces);
-    }
-
-    @Override
-    public Set<Interface> getInterfacesByPort(ConnectPoint cp) {
-        return interfaces.stream().filter(intf -> cp.equals(intf.connectPoint()))
-                .collect(Collectors.toSet());
-    }
-
-    @Override
-    public Set<Interface> getInterfaces() {
-        return interfaces;
-    }
-
-    @Override
-    public Interface getMatchingInterface(IpAddress ip) {
-        return getMatchingInterfacesStream(ip).findFirst().orElse(null);
-    }
-
-    @Override
-    public Set<Interface> getMatchingInterfaces(IpAddress ip) {
-        return getMatchingInterfacesStream(ip).collect(toSet());
-    }
-
-    private Stream<Interface> getMatchingInterfacesStream(IpAddress ip) {
-        return interfaces.stream()
-                .filter(intf -> intf.ipAddressesList().stream()
-                        .anyMatch(intfIp -> intfIp.subnetAddress().contains(ip)));
-    }
-
-    @Override
-    public boolean isConfigured(ConnectPoint connectPoint) {
-        Set<Interface> intfs = getInterfacesByPort(connectPoint);
-        if (intfs == null) {
-            return false;
-        }
-        for (Interface intf : intfs) {
-            if (!intf.ipAddressesList().isEmpty() || intf.vlan() != VlanId.NONE
-                    || intf.vlanNative() != VlanId.NONE
-                    || intf.vlanUntagged() != VlanId.NONE
-                    || !intf.vlanTagged().isEmpty()) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
deleted file mode 100644
index fe5df5d..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2017-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 org.onosproject.net.HostLocation;
-
-/**
- * Mocks the LinkHandler in SR.
- *
- */
-public class MockLinkHandler extends LinkHandler {
-
-    MockLinkHandler(SegmentRoutingManager srManager) {
-        super(srManager, null);
-    }
-
-    @Override
-    void checkUplinksForHost(HostLocation loc) {
-        // currently does nothing - can be extended to be a useful mock when
-        // implementing unit tests for link handling
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java
deleted file mode 100644
index 5494e27..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2017-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.ImmutableSet;
-import org.onosproject.mastership.MastershipServiceAdapter;
-import org.onosproject.net.DeviceId;
-
-import java.util.Set;
-
-/**
- * Mock Mastership Service.
- */
-public class MockMastershipService extends MastershipServiceAdapter {
-    // A set of devices of which we have mastership.
-    private Set<DeviceId> localDevices;
-
-    MockMastershipService(Set<DeviceId> localDevices) {
-        this.localDevices = ImmutableSet.copyOf(localDevices);
-    }
-
-    @Override
-    public boolean isLocalMaster(DeviceId deviceId) {
-        return localDevices.contains(deviceId);
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNeighbourResolutionService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNeighbourResolutionService.java
deleted file mode 100644
index 5a41149..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNeighbourResolutionService.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2019-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 org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.neighbour.NeighbourHandlerRegistration;
-import org.onosproject.net.neighbour.NeighbourMessageHandler;
-import org.onosproject.net.neighbour.NeighbourResolutionService;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Mock Neighbour Resolution Service.
- */
-public class MockNeighbourResolutionService implements NeighbourResolutionService {
-    @Override
-    public void registerNeighbourHandler(ConnectPoint connectPoint,
-                                         NeighbourMessageHandler handler, ApplicationId appId) {
-
-    }
-
-    @Override
-    public void registerNeighbourHandler(Interface intf,
-                                         NeighbourMessageHandler handler, ApplicationId appId) {
-
-    }
-
-    @Override
-    public void unregisterNeighbourHandler(ConnectPoint connectPoint,
-                                           NeighbourMessageHandler handler, ApplicationId appId) {
-
-    }
-
-    @Override
-    public void unregisterNeighbourHandler(Interface intf,
-                                           NeighbourMessageHandler handler, ApplicationId appId) {
-
-    }
-
-    @Override
-    public void unregisterNeighbourHandlers(ApplicationId appId) {
-
-    }
-
-    @Override
-    public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
-        return null;
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java
deleted file mode 100644
index 12d57ea..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2017-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.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Mock Network Config Registry.
- */
-class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
-    private Set<Config> configs = Sets.newHashSet();
-
-    void applyConfig(Config config) {
-        configs.add(config);
-    }
-
-    @Override
-    public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
-        Config c = configs.stream()
-                .filter(config -> subject.equals(config.subject()))
-                .filter(config -> configClass.equals(config.getClass()))
-                .findFirst().orElse(null);
-        return (C) c;
-    }
-
-    @Override
-    public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
-        Config c = configs.stream()
-                .filter(config -> subject.equals(config.subject()))
-                .filter(config -> configClass.equals(config.getClass()))
-                .findFirst().orElseGet(() -> {
-                    if (configClass.equals(BasicDeviceConfig.class)) {
-                        BasicDeviceConfig deviceConfig = new BasicDeviceConfig();
-                        ObjectMapper mapper = new ObjectMapper();
-                        deviceConfig.init((DeviceId) subject, ((DeviceId) subject).toString(),
-                                          JsonNodeFactory.instance.objectNode(), mapper, config -> {
-                                });
-                        return deviceConfig;
-                    }
-                    return null;
-                });
-        return (C) c;
-    }
-
-    @Override
-    public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subject, Class<C> configClass) {
-        ImmutableSet.Builder<S> builder = ImmutableSet.builder();
-        String cName = configClass.getName();
-        configs.forEach(k -> {
-            if (subject.isInstance(k.subject()) && Objects.equals(cName, k.getClass().getName())) {
-                builder.add((S) k.subject());
-            }
-        });
-        return builder.build();
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockPacketService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockPacketService.java
deleted file mode 100644
index 73a8b65..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockPacketService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2019-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.Maps;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.packet.DeserializationException;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.net.packet.PacketServiceAdapter;
-
-import java.util.Map;
-
-/**
- * Mock Packet Service.
- * It is used for tests related to packet-ins management.
- */
-public class MockPacketService extends PacketServiceAdapter {
-
-    private final Map<MacAddress, Pair<OutboundPacket, Ethernet>> outBoundPackets = Maps.newHashMap();
-
-    @Override
-    public void emit(OutboundPacket packet) {
-        try {
-            Ethernet ethernetPacket = Ethernet.deserializer().deserialize(packet.data().array(),
-                                                                          packet.data().arrayOffset(),
-                                                                          packet.data().array().length);
-            outBoundPackets.put(ethernetPacket.getDestinationMAC(), Pair.of(packet, ethernetPacket));
-        } catch (DeserializationException e) {
-
-        }
-    }
-
-    Ethernet getEthernetPacket(MacAddress key) {
-        Pair<OutboundPacket, Ethernet> pair = outBoundPackets.get(key);
-        return pair != null ? pair.getRight() : null;
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRouteService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRouteService.java
deleted file mode 100644
index c3730dd..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRouteService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2017-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.Sets;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteInfo;
-import org.onosproject.routeservice.RouteServiceAdapter;
-import org.onosproject.routeservice.RouteTableId;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Mock Route Service.
- * We assume there is only one routing table named "default".
- */
-public class MockRouteService extends RouteServiceAdapter {
-    private Map<IpPrefix, Set<ResolvedRoute>> routeStore;
-
-    MockRouteService(Map<IpPrefix, Set<ResolvedRoute>> routeStore) {
-        this.routeStore = routeStore;
-    }
-
-    @Override
-    public Collection<RouteInfo> getRoutes(RouteTableId id) {
-        return routeStore.entrySet().stream().map(e -> {
-            IpPrefix prefix = e.getKey();
-            Set<ResolvedRoute> resolvedRoutes = e.getValue();
-            ResolvedRoute bestRoute =  resolvedRoutes.stream().findFirst().orElse(null);
-            return new RouteInfo(prefix, bestRoute, resolvedRoutes);
-        }).collect(Collectors.toSet());
-    }
-
-    @Override
-    public Collection<RouteTableId> getRouteTables() {
-        return Sets.newHashSet(new RouteTableId("default"));
-    }
-
-    @Override
-    public Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip) {
-        return this.routeStore.get(ip.toIpPrefix()).stream()
-                .findFirst();
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java
deleted file mode 100644
index 4d222d8..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017-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 org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.Objective;
-
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * Mock Routing Rule Populator.
- */
-public class MockRoutingRulePopulator extends RoutingRulePopulator {
-    private Map<MockRoutingTableKey, MockRoutingTableValue> routingTable;
-
-    MockRoutingRulePopulator(SegmentRoutingManager srManager,
-                             Map<MockRoutingTableKey, MockRoutingTableValue> routingTable) {
-        super(srManager);
-        this.routingTable = routingTable;
-    }
-
-    @Override
-    public CompletableFuture<Objective> populateRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
-                                                      VlanId hostVlanId, PortNumber outPort, boolean directHost) {
-        MockRoutingTableKey rtKey = new MockRoutingTableKey(deviceId, prefix);
-        MockRoutingTableValue rtValue = new MockRoutingTableValue(outPort, hostMac, hostVlanId);
-        routingTable.put(rtKey, rtValue);
-        return CompletableFuture.completedFuture(null);
-    }
-
-    @Override
-    public CompletableFuture<Objective> revokeRoute(DeviceId deviceId, IpPrefix prefix,
-                            MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
-        MockRoutingTableKey rtKey = new MockRoutingTableKey(deviceId, prefix);
-        MockRoutingTableValue rtValue = new MockRoutingTableValue(outPort, hostMac, hostVlanId);
-        routingTable.remove(rtKey, rtValue);
-        return CompletableFuture.completedFuture(null);
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java
deleted file mode 100644
index 4f09c2a..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2017-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 org.onlab.packet.IpPrefix;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Mock Routing Table Key.
- */
-class MockRoutingTableKey {
-    DeviceId deviceId;
-    IpPrefix ipPrefix;
-
-    MockRoutingTableKey(DeviceId deviceId, IpPrefix ipPrefix) {
-        this.deviceId = deviceId;
-        this.ipPrefix = ipPrefix;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof MockRoutingTableKey)) {
-            return false;
-        }
-        final MockRoutingTableKey other = (MockRoutingTableKey) obj;
-        return Objects.equals(this.deviceId, other.deviceId) &&
-                Objects.equals(this.ipPrefix, other.ipPrefix);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(deviceId, ipPrefix);
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java
deleted file mode 100644
index 5842d2d..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017-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 org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.PortNumber;
-
-import java.util.Objects;
-
-/**
- * Mock Routing Table Value.
- */
-class MockRoutingTableValue {
-    PortNumber portNumber;
-    MacAddress macAddress;
-    VlanId vlanId;
-
-    MockRoutingTableValue(PortNumber portNumber, MacAddress macAddress, VlanId vlanId) {
-        this.portNumber = portNumber;
-        this.macAddress = macAddress;
-        this.vlanId = vlanId;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof MockRoutingTableValue)) {
-            return false;
-        }
-        final MockRoutingTableValue other = (MockRoutingTableValue) obj;
-        return Objects.equals(this.portNumber, other.portNumber) &&
-                Objects.equals(this.macAddress, other.macAddress) &&
-                Objects.equals(this.vlanId, other.vlanId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(portNumber, macAddress, vlanId);
-    }
-}
-
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java
deleted file mode 100644
index ad098b4..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2017-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 org.onosproject.core.DefaultApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Mock Segment Routing Manager.
- */
-public class MockSegmentRoutingManager extends SegmentRoutingManager {
-    private Map<Integer, TrafficTreatment> nextTable;
-    private AtomicInteger atomicNextId = new AtomicInteger();
-
-    MockSegmentRoutingManager(Map<Integer, TrafficTreatment> nextTable) {
-        appId = new DefaultApplicationId(1, SegmentRoutingManager.APP_NAME);
-        this.nextTable = nextTable;
-    }
-
-    @Override
-    public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
-                                      TrafficTreatment treatment,
-                                      TrafficSelector meta,
-                                      boolean createIfMissing) {
-        int nextId = atomicNextId.incrementAndGet();
-        nextTable.put(nextId, treatment);
-        return nextId;
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PortAuthTrackerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PortAuthTrackerTest.java
deleted file mode 100644
index 6ab4bad..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PortAuthTrackerTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2017-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.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.DefaultApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.PortAuthTracker.BlockState;
-import org.onosproject.segmentrouting.config.BlockedPortsConfig;
-import org.onosproject.segmentrouting.config.BlockedPortsConfigTest;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.onosproject.net.ConnectPoint.deviceConnectPoint;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.onosproject.segmentrouting.PortAuthTracker.BlockState.AUTHENTICATED;
-import static org.onosproject.segmentrouting.PortAuthTracker.BlockState.BLOCKED;
-import static org.onosproject.segmentrouting.PortAuthTracker.BlockState.UNCHECKED;
-
-/**
- * Unit Tests for {@link PortAuthTracker}.
- */
-public class PortAuthTrackerTest {
-    private static final ApplicationId APP_ID = new DefaultApplicationId(1, "foo");
-    private static final String KEY = "blocked";
-    private static final ObjectMapper MAPPER = new ObjectMapper();
-    private static final String PATH_CFG = "/blocked-ports.json";
-    private static final String PATH_CFG_ALT = "/blocked-ports-alt.json";
-
-    private static final String DEV1 = "of:0000000000000001";
-    private static final String DEV3 = "of:0000000000000003";
-    private static final String DEV4 = "of:0000000000000004";
-
-    private BlockedPortsConfig cfg;
-    private AugmentedPortAuthTracker tracker;
-
-    private void print(String s) {
-        System.out.println(s);
-    }
-
-    private void print(Object o) {
-        print(o.toString());
-    }
-
-    private void print(String fmt, Object... params) {
-        print(String.format(fmt, params));
-    }
-
-    private void title(String s) {
-        print("=== %s ===", s);
-    }
-
-    private BlockedPortsConfig makeConfig(String path) throws IOException {
-        InputStream blockedPortsJson = BlockedPortsConfigTest.class
-                .getResourceAsStream(path);
-        JsonNode node = MAPPER.readTree(blockedPortsJson);
-        BlockedPortsConfig cfg = new BlockedPortsConfig();
-        cfg.init(APP_ID, KEY, node, MAPPER, null);
-        return cfg;
-    }
-
-    ConnectPoint cp(String devId, int port) {
-        return ConnectPoint.deviceConnectPoint(devId + "/" + port);
-    }
-
-    @Before
-    public void setUp() throws IOException {
-        cfg = makeConfig(PATH_CFG);
-        tracker = new AugmentedPortAuthTracker();
-    }
-
-    private void verifyPortState(String devId, int first, BlockState... states) {
-        DeviceId dev = deviceId(devId);
-        int last = first + states.length;
-        int pn = first;
-        int i = 0;
-        while (pn < last) {
-            PortNumber pnum = portNumber(pn);
-            BlockState actual = tracker.currentState(dev, pnum);
-            print("%s/%s [%s]  --> %s", devId, pn, states[i], actual);
-            assertEquals("oops: " + devId + "/" + pn + "~" + actual,
-                         states[i], actual);
-            pn++;
-            i++;
-        }
-    }
-
-    @Test
-    public void basic() {
-        title("basic");
-        print(tracker);
-        print(cfg);
-
-        assertEquals("wrong entry count", 0, tracker.entryCount());
-
-        // let's assume that the net config just got loaded..
-        tracker.configurePortBlocking(cfg);
-        assertEquals("wrong entry count", 13, tracker.entryCount());
-
-        verifyPortState(DEV1, 1, BLOCKED, BLOCKED, BLOCKED, BLOCKED, UNCHECKED);
-        verifyPortState(DEV1, 6, UNCHECKED, BLOCKED, BLOCKED, BLOCKED, UNCHECKED);
-
-        verifyPortState(DEV3, 1, UNCHECKED, UNCHECKED, UNCHECKED);
-        verifyPortState(DEV3, 6, UNCHECKED, BLOCKED, BLOCKED, BLOCKED, UNCHECKED);
-
-        verifyPortState(DEV4, 1, BLOCKED, UNCHECKED, UNCHECKED, UNCHECKED, BLOCKED);
-    }
-
-    @Test
-    public void logonLogoff() {
-        title("logonLogoff");
-
-        tracker.configurePortBlocking(cfg);
-        assertEquals("wrong entry count", 13, tracker.entryCount());
-        verifyPortState(DEV1, 1, BLOCKED, BLOCKED, BLOCKED);
-
-        ConnectPoint cp = deviceConnectPoint(DEV1 + "/2");
-        tracker.radiusAuthorize(cp);
-        print("");
-        verifyPortState(DEV1, 1, BLOCKED, AUTHENTICATED, BLOCKED);
-
-        tracker.radiusLogoff(cp);
-        print("");
-        verifyPortState(DEV1, 1, BLOCKED, BLOCKED, BLOCKED);
-    }
-
-    @Test
-    public void installedFlows() {
-        title("installed flows");
-
-        assertEquals(0, tracker.installed.size());
-        tracker.configurePortBlocking(cfg);
-        assertEquals(13, tracker.installed.size());
-
-        assertTrue(tracker.installed.contains(cp(DEV1, 1)));
-        assertTrue(tracker.installed.contains(cp(DEV3, 7)));
-        assertTrue(tracker.installed.contains(cp(DEV4, 5)));
-    }
-
-    @Test
-    public void flowsLogonLogoff() {
-        title("flows logon logoff");
-
-        tracker.configurePortBlocking(cfg);
-
-        // let's pick a connect point from the configuration
-        ConnectPoint cp = cp(DEV4, 5);
-
-        assertTrue(tracker.installed.contains(cp));
-        assertEquals(0, tracker.cleared.size());
-
-        tracker.resetMetrics();
-        tracker.radiusAuthorize(cp);
-        // verify we requested the blocking flow to be cleared
-        assertTrue(tracker.cleared.contains(cp));
-
-        tracker.resetMetrics();
-        assertEquals(0, tracker.installed.size());
-        tracker.radiusLogoff(cp);
-        // verify we requested the blocking flow to be reinstated
-        assertTrue(tracker.installed.contains(cp));
-    }
-
-    @Test
-    public void uncheckedPortIgnored() {
-        title("unchecked port ignored");
-
-        tracker.configurePortBlocking(cfg);
-        tracker.resetMetrics();
-
-        // let's pick a connect point NOT in the configuration
-        ConnectPoint cp = cp(DEV4, 2);
-        assertEquals(BlockState.UNCHECKED, tracker.currentState(cp));
-
-        assertEquals(0, tracker.installed.size());
-        assertEquals(0, tracker.cleared.size());
-        tracker.radiusAuthorize(cp);
-        assertEquals(0, tracker.installed.size());
-        assertEquals(0, tracker.cleared.size());
-        tracker.radiusLogoff(cp);
-        assertEquals(0, tracker.installed.size());
-        assertEquals(0, tracker.cleared.size());
-    }
-
-    @Test
-    public void reconfiguration() throws IOException {
-        title("reconfiguration");
-
-        /* see 'blocked-ports.json' and 'blocked-ports-alt.json'
-
-          cfg:  "1": ["1-4", "7-9"],
-                "3": ["7-9"],
-                "4": ["1", "5", "9"]
-
-          alt:  "1": ["1-9"],
-                "3": ["7"],
-                "4": ["1"]
-         */
-        tracker.configurePortBlocking(cfg);
-        // dev1: ports 5 and 6 are NOT configured in the original CFG
-        assertFalse(tracker.installed.contains(cp(DEV1, 5)));
-        assertFalse(tracker.installed.contains(cp(DEV1, 6)));
-
-        tracker.resetMetrics();
-        assertEquals(0, tracker.installed.size());
-        assertEquals(0, tracker.cleared.size());
-
-        BlockedPortsConfig alt = makeConfig(PATH_CFG_ALT);
-        tracker.configurePortBlocking(alt);
-
-        // dev1: ports 5 and 6 ARE configured in the alternate CFG
-        assertTrue(tracker.installed.contains(cp(DEV1, 5)));
-        assertTrue(tracker.installed.contains(cp(DEV1, 6)));
-
-        // also, check for the ports that were decommissioned
-        assertTrue(tracker.cleared.contains(cp(DEV3, 8)));
-        assertTrue(tracker.cleared.contains(cp(DEV3, 9)));
-        assertTrue(tracker.cleared.contains(cp(DEV4, 5)));
-        assertTrue(tracker.cleared.contains(cp(DEV4, 9)));
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
deleted file mode 100644
index f2a439b..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Copyright 2017-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.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onosproject.routeservice.RouteEvent;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.TestConsistentMap;
-import org.onosproject.store.service.TestConsistentMultimap;
-
-import java.util.Map;
-import java.util.Set;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.reset;
-import static org.junit.Assert.*;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-/**
- * Unit test for {@link RouteHandler}.
- */
-public class RouteHandlerTest {
-    private SegmentRoutingManager srManager;
-    private RouteHandler routeHandler;
-    private HostService hostService;
-
-    // Mocked routing and bridging tables
-    private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
-            Maps.newConcurrentMap();
-    private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
-            Maps.newConcurrentMap();
-    private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
-    // Mocked Next Id
-    private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
-    private static final Map<IpPrefix, Set<ResolvedRoute>> ROUTE_STORE = Maps.newConcurrentMap();
-
-    private static final IpPrefix P1 = IpPrefix.valueOf("10.0.0.0/24");
-
-    // Single homed router 1
-    private static final IpAddress N1 = IpAddress.valueOf("10.0.1.1");
-    private static final MacAddress M1 = MacAddress.valueOf("00:00:00:00:00:01");
-    private static final VlanId V1 = VlanId.vlanId((short) 1);
-    private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
-    private static final Route R1 = new Route(Route.Source.STATIC, P1, N1);
-    private static final ResolvedRoute RR1 = new ResolvedRoute(R1, M1, V1);
-    private static final Route DHCP_R1 = new Route(Route.Source.DHCP, P1, N1);
-    private static final ResolvedRoute DHCP_RR1 = new ResolvedRoute(DHCP_R1, M1, V1);
-
-    // Single homed router 2
-    private static final IpAddress N2 = IpAddress.valueOf("10.0.2.1");
-    private static final MacAddress M2 = MacAddress.valueOf("00:00:00:00:00:02");
-    private static final VlanId V2 = VlanId.vlanId((short) 2);
-    private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000002/2");
-    private static final Route R2 = new Route(Route.Source.STATIC, P1, N2);
-    private static final ResolvedRoute RR2 = new ResolvedRoute(R2, M2, V2);
-
-    // Dual homed router 1
-    private static final IpAddress N3 = IpAddress.valueOf("10.0.3.1");
-    private static final MacAddress M3 = MacAddress.valueOf("00:00:00:00:00:03");
-    private static final VlanId V3 = VlanId.vlanId((short) 3);
-    private static final Route R3 = new Route(Route.Source.STATIC, P1, N3);
-    private static final ResolvedRoute RR3 = new ResolvedRoute(R3, M3, V3);
-    private static final Route DHCP_R3 = new Route(Route.Source.DHCP, P1, N3);
-    private static final ResolvedRoute DHCP_RR3 = new ResolvedRoute(DHCP_R3, M3, V3);
-
-    // Single homed router 3
-    private static final IpAddress N4 = IpAddress.valueOf("10.0.4.1");
-    private static final MacAddress M4 = MacAddress.valueOf("00:00:00:00:00:04");
-    private static final VlanId V4 = VlanId.vlanId((short) 4);
-    private static final ConnectPoint CP4 = ConnectPoint.deviceConnectPoint("of:0000000000000004/4");
-    private static final Route R4 = new Route(Route.Source.STATIC, P1, N4);
-    private static final ResolvedRoute RR4 = new ResolvedRoute(R4, M4, V4);
-
-    // Hosts
-    private static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(M1, V1), M1, V1,
-            Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N1), false);
-    private static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(M2, V2), M2, V2,
-            Sets.newHashSet(new HostLocation(CP2, 0)), Sets.newHashSet(N2), false);
-    private static final Host H3D = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
-            Sets.newHashSet(new HostLocation(CP1, 0), new HostLocation(CP2, 0)), Sets.newHashSet(N3), false);
-    private static final Host H3S = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
-            Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N3), false);
-    private static final Host H4 = new DefaultHost(ProviderId.NONE, HostId.hostId(M4, V4), M4, V4,
-            Sets.newHashSet(new HostLocation(CP4, 0)), Sets.newHashSet(N4), false);
-
-    // Pair Local Port
-    private static final PortNumber P9 = PortNumber.portNumber(9);
-
-    // A set of hosts
-    private static final Set<Host> HOSTS = Sets.newHashSet(H1, H2, H3D, H4);
-    private static final Set<Host> HOSTS_ONE_FAIL = Sets.newHashSet(H1, H2, H3S);
-    private static final Set<Host> HOSTS_BOTH_FAIL = Sets.newHashSet(H1, H2);
-    // A set of devices of which we have mastership
-    private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(CP1.deviceId(), CP2.deviceId());
-    // A set of interfaces
-    private static final InterfaceIpAddress IF_IP1 =
-            new InterfaceIpAddress(IpAddress.valueOf("10.0.1.254"), IpPrefix.valueOf("10.0.1.254/24"));
-    private static final InterfaceIpAddress IF_IP3 =
-            new InterfaceIpAddress(IpAddress.valueOf("10.0.3.254"), IpPrefix.valueOf("10.0.3.254/24"));
-    private static final Interface IF_CP1 = new Interface("if-cp1", CP1, Lists.newArrayList(IF_IP1, IF_IP3),
-            null, null, null, null, null);
-    private static final Interface IF_CP2 = new Interface("if-cp2", CP2, Lists.newArrayList(IF_IP1, IF_IP3),
-            null, null, null, null, null);
-    private static final Set<Interface> INTERFACES = Sets.newHashSet(IF_CP1, IF_CP2);
-
-    @Before
-    public void setUp() {
-        ObjectMapper mapper = new ObjectMapper();
-        ConfigApplyDelegate delegate = config -> { };
-
-        SegmentRoutingDeviceConfig dev1Config = new SegmentRoutingDeviceConfig();
-        JsonNode dev1Tree = mapper.createObjectNode();
-        dev1Config.init(CP1.deviceId(), "host-handler-test", dev1Tree, mapper, delegate);
-        dev1Config.setPairDeviceId(CP2.deviceId()).setPairLocalPort(P9);
-
-        SegmentRoutingDeviceConfig dev2Config = new SegmentRoutingDeviceConfig();
-        JsonNode dev2Tree = mapper.createObjectNode();
-        dev2Config.init(CP2.deviceId(), "host-handler-test", dev2Tree, mapper, delegate);
-        dev2Config.setPairDeviceId(CP1.deviceId()).setPairLocalPort(P9);
-
-        MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
-        mockNetworkConfigRegistry.applyConfig(dev1Config);
-        mockNetworkConfigRegistry.applyConfig(dev2Config);
-
-        // Initialize Segment Routing Manager
-        srManager = new MockSegmentRoutingManager(NEXT_TABLE);
-        srManager.storageService = createMock(StorageService.class);
-        expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
-        expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
-                new TestConsistentMultimap.Builder<>()).anyTimes();
-        replay(srManager.storageService);
-        srManager.cfgService = new NetworkConfigRegistryAdapter();
-        srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
-        srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
-        srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
-        srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
-        srManager.interfaceService = new MockInterfaceService(INTERFACES);
-        srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
-        hostService = new MockHostService(HOSTS);
-        srManager.hostService = hostService;
-        srManager.cfgService = mockNetworkConfigRegistry;
-        srManager.routeService = new MockRouteService(ROUTE_STORE);
-        srManager.phasedRecoveryService = createMock(PhasedRecoveryService.class);
-        expect(srManager.phasedRecoveryService.isEnabled()).andReturn(true).anyTimes();
-        replay(srManager.phasedRecoveryService);
-
-        routeHandler = new RouteHandler(srManager);
-
-        ROUTING_TABLE.clear();
-        BRIDGING_TABLE.clear();
-        SUBNET_TABLE.clear();
-    }
-
-    @Test
-    public void init() {
-        ROUTE_STORE.put(P1, Sets.newHashSet(RR1));
-
-        routeHandler.init(CP1.deviceId());
-
-        assertEquals(1, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-
-        assertEquals(1, SUBNET_TABLE.size());
-    }
-
-    @Test
-    public void initTwoNextHops() {
-        ROUTE_STORE.put(P1, Sets.newHashSet(RR1, RR2));
-
-        routeHandler.init(CP1.deviceId());
-
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M2, rtv2.macAddress);
-        assertEquals(V2, rtv2.vlanId);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-    }
-
-    // Only one of two dual-homed next hops present.
-    // Expect one routing table to be programmed with direct flow.
-    // The other is not programmed, not even for subnet
-    @Test
-    public void initDhcpRouteSingleDualHomeNextHop() {
-        ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR1));
-
-        routeHandler.init(CP1.deviceId());
-
-        assertEquals(1, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-
-        assertEquals(1, SUBNET_TABLE.size());
-    }
-
-    // Both dual-homed next hops present.
-    // Expect both routing table to be programmed with direct flow
-    @Test
-    public void initDhcpRouteBothDualHomeNextHop() {
-        ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR3));
-
-        routeHandler.init(CP1.deviceId());
-
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M3, rtv1.macAddress);
-        assertEquals(V3, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M3, rtv2.macAddress);
-        assertEquals(V3, rtv2.vlanId);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-    }
-
-    @Test
-    public void processRouteAdded() {
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.addSubnet(CP1, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1));
-        routeHandler.processRouteAdded(re);
-
-        assertEquals(1, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-
-        assertEquals(1, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void processRouteUpdated() {
-        processRouteAdded();
-
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.removeSubnet(CP1, P1);
-        expectLastCall().once();
-        srManager.deviceConfiguration.addSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, RR2, RR1, Sets.newHashSet(RR2),
-                Sets.newHashSet(RR1));
-        routeHandler.processRouteUpdated(re);
-
-        // Note: We shouldn't remove the old nexthop during the occasion of route update
-        //       since the populate subnet will take care of it and point it to an ECMP group
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M2, rtv2.macAddress);
-        assertEquals(V2, rtv2.vlanId);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(1, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void processRouteRemoved() {
-        processRouteAdded();
-
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.removeSubnet(CP1, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1));
-        routeHandler.processRouteRemoved(re);
-
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, SUBNET_TABLE.size());
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testTwoSingleHomedAdded() {
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.addSubnet(CP1, P1);
-        expectLastCall().once();
-        srManager.deviceConfiguration.addSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
-        routeHandler.processRouteAdded(re);
-
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(M2, rtv2.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(V2, rtv2.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testOneDualHomedAdded() {
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.addSubnet(CP1, P1);
-        expectLastCall().once();
-        srManager.deviceConfiguration.addSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR3, Sets.newHashSet(RR3));
-        routeHandler.processRouteAdded(re);
-
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M3, rtv1.macAddress);
-        assertEquals(M3, rtv2.macAddress);
-        assertEquals(V3, rtv1.vlanId);
-        assertEquals(V3, rtv2.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testOneSingleHomedToTwoSingleHomed() {
-        processRouteAdded();
-
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.addSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
-                Sets.newHashSet(RR1, RR2), Sets.newHashSet(RR1));
-        routeHandler.processAlternativeRoutesChanged(re);
-
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(M2, rtv2.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(V2, rtv2.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testTwoSingleHomedToOneSingleHomed() {
-        testTwoSingleHomedAdded();
-
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.removeSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
-                Sets.newHashSet(RR1), Sets.newHashSet(RR1, RR2));
-        routeHandler.processAlternativeRoutesChanged(re);
-
-        // Note: We shouldn't remove the old nexthop during the occasion of route update
-        //       since the populate subnet will take care of it and point it to an ECMP group
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-
-        assertEquals(1, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    // TODO Add test cases for two single homed next hop at same location
-
-    @Test
-    public void testDualHomedSingleLocationFail() {
-        testOneDualHomedAdded();
-
-        ROUTE_STORE.put(P1, Sets.newHashSet(RR3));
-
-        reset(srManager.deviceConfiguration);
-        expect(srManager.deviceConfiguration.getBatchedSubnets(H3D.id()))
-                .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
-        srManager.deviceConfiguration.removeSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3S, H3D);
-        routeHandler.processHostMovedEvent(he);
-
-        // We do not remove the route on CP2. Instead, we let the subnet population overrides it
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M3, rtv1.macAddress);
-        assertEquals(V3, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-
-        // ECMP route table hasn't changed
-        assertEquals(1, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testDualHomedBothLocationFail() {
-        testDualHomedSingleLocationFail();
-
-        hostService = new MockHostService(HOSTS_ONE_FAIL);
-
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.removeSubnet(CP1, P1);
-        expectLastCall().once();
-        srManager.deviceConfiguration.removeSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
-        routeHandler.processRouteRemoved(re);
-
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, SUBNET_TABLE.size());
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testSingleHomedToDualHomed() {
-        testDualHomedSingleLocationFail();
-
-        reset(srManager.deviceConfiguration);
-        expect(srManager.deviceConfiguration.getBatchedSubnets(H3S.id()))
-                .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
-        srManager.deviceConfiguration.addSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3D, H3S);
-        routeHandler.processHostMovedEvent(he);
-
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M3, rtv1.macAddress);
-        assertEquals(M3, rtv2.macAddress);
-        assertEquals(V3, rtv1.vlanId);
-        assertEquals(V3, rtv2.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testTwoSingleHomedRemoved() {
-        testTwoSingleHomedAdded();
-
-        hostService = new MockHostService(HOSTS_BOTH_FAIL);
-
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.removeSubnet(CP1, P1);
-        expectLastCall().once();
-        srManager.deviceConfiguration.removeSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1, RR2));
-        routeHandler.processRouteRemoved(re);
-
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, SUBNET_TABLE.size());
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testOneDualHomeRemoved() {
-        testOneDualHomedAdded();
-
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.removeSubnet(CP1, P1);
-        expectLastCall().once();
-        srManager.deviceConfiguration.removeSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
-        routeHandler.processRouteRemoved(re);
-
-        assertEquals(0, ROUTING_TABLE.size());
-        assertEquals(0, SUBNET_TABLE.size());
-
-        verify(srManager.deviceConfiguration);
-    }
-
-    @Test
-    public void testMoreThanTwoNextHop() {
-        // next hop = CP1, CP2
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.addSubnet(CP1, P1);
-        srManager.deviceConfiguration.addSubnet(CP2, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
-        routeHandler.processRouteAdded(re);
-
-        assertEquals(2, ROUTING_TABLE.size());
-        MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-        MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M2, rtv2.macAddress);
-        assertEquals(V2, rtv2.vlanId);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-
-        // next hop = CP1, CP2, CP4 (invalid)
-        re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
-                Sets.newHashSet(RR1, RR2, RR4), Sets.newHashSet(RR1, RR2));
-        routeHandler.processAlternativeRoutesChanged(re);
-
-        assertEquals(2, ROUTING_TABLE.size());
-        rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
-        assertEquals(M1, rtv1.macAddress);
-        assertEquals(V1, rtv1.vlanId);
-        assertEquals(CP1.port(), rtv1.portNumber);
-        rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M2, rtv2.macAddress);
-        assertEquals(V2, rtv2.vlanId);
-        assertEquals(CP2.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
-        // next hop = CP2, CP4
-        reset(srManager.deviceConfiguration);
-        srManager.deviceConfiguration.addSubnet(CP2, P1);
-        srManager.deviceConfiguration.addSubnet(CP4, P1);
-        expectLastCall().once();
-        replay(srManager.deviceConfiguration);
-
-        re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
-                Sets.newHashSet(RR2, RR4), Sets.newHashSet(RR1, RR2, RR4));
-        routeHandler.processAlternativeRoutesChanged(re);
-
-        assertEquals(2, ROUTING_TABLE.size());
-        rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
-        assertEquals(M2, rtv1.macAddress);
-        assertEquals(V2, rtv1.vlanId);
-        assertEquals(CP2.port(), rtv1.portNumber);
-        rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1));
-        assertEquals(M4, rtv2.macAddress);
-        assertEquals(V4, rtv2.vlanId);
-        assertEquals(CP4.port(), rtv2.portNumber);
-
-        assertEquals(2, SUBNET_TABLE.size());
-        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-        assertTrue(SUBNET_TABLE.get(CP4).contains(P1));
-
-        verify(srManager.deviceConfiguration);
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RoutingRulePopulatorTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RoutingRulePopulatorTest.java
deleted file mode 100644
index c8afeef..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RoutingRulePopulatorTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2018-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.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-
-import java.util.List;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.*;
-
-public class RoutingRulePopulatorTest {
-    private RoutingRulePopulator rrp;
-    private SegmentRoutingManager srManager;
-    private InterfaceService interfaceService;
-    private DeviceService deviceService;
-
-    private final DeviceId devId1 = DeviceId.deviceId("of:1");
-    private final Device dev1 = new DefaultDevice(ProviderId.NONE, devId1, Device.Type.SWITCH,
-            null, null, null, null, null);
-
-    private final PortNumber p1 = PortNumber.portNumber(1);
-    private final PortNumber p2 = PortNumber.portNumber(2);
-    private final PortNumber p3 = PortNumber.portNumber(3);
-    private final PortNumber p4 = PortNumber.portNumber(4);
-    private final PortNumber p5 = PortNumber.portNumber(5);
-
-    private final VlanId v10 = VlanId.vlanId((short) 10);
-    private final VlanId v20 = VlanId.vlanId((short) 20);
-    private VlanId vInt;
-
-    private final Interface u10 = new Interface(null, new ConnectPoint(devId1, p1),
-            null, null, null, v10, null, null);
-    private final Interface t10 = new Interface(null, new ConnectPoint(devId1, p2),
-            null, null, null, null, Sets.newHashSet(v10), null);
-    private final Interface t10n20 = new Interface(null, new ConnectPoint(devId1, p3),
-            null, null, null, null, Sets.newHashSet(v10), v20);
-
-    @Before
-    public void setUp() throws Exception {
-        Set<Interface> interfaces = Sets.newHashSet(u10, t10, t10n20);
-        interfaceService = new MockInterfaceService(interfaces);
-        deviceService = EasyMock.createMock(DeviceService.class);
-        srManager = new MockSegmentRoutingManager(Maps.newHashMap());
-        srManager.deviceConfiguration =  EasyMock.createMock(DeviceConfiguration.class);
-        srManager.interfaceService = interfaceService;
-        srManager.deviceService = deviceService;
-        vInt = srManager.getDefaultInternalVlan();
-        rrp = new RoutingRulePopulator(srManager);
-    }
-
-    // All ports are enabled
-    @Test
-    public void testNoMoreEnabledPortCase1() throws Exception {
-        Port port1 = new DefaultPort(dev1, p1, true);
-        Port port2 = new DefaultPort(dev1, p2, true);
-        Port port3 = new DefaultPort(dev1, p3, true);
-        Port port4 = new DefaultPort(dev1, p4, true);
-        Port port5 = new DefaultPort(dev1, p5, true);
-        List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
-        expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
-        replay(deviceService);
-        assertFalse(rrp.noMoreEnabledPort(devId1, v10));
-        assertFalse(rrp.noMoreEnabledPort(devId1, v20));
-        assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
-    }
-
-    // Disable port 1
-    @Test
-    public void testNoMoreEnabledPortCase2() throws Exception {
-        Port port1 = new DefaultPort(dev1, p1, false);
-        Port port2 = new DefaultPort(dev1, p2, true);
-        Port port3 = new DefaultPort(dev1, p3, true);
-        Port port4 = new DefaultPort(dev1, p4, true);
-        Port port5 = new DefaultPort(dev1, p5, true);
-        List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
-        expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
-        replay(deviceService);
-        assertFalse(rrp.noMoreEnabledPort(devId1, v10));
-        assertFalse(rrp.noMoreEnabledPort(devId1, v20));
-        assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
-    }
-
-    // Disable port 1 and 3
-    @Test
-    public void testNoMoreEnabledPortCase3() throws Exception {
-        Port port1 = new DefaultPort(dev1, p1, false);
-        Port port2 = new DefaultPort(dev1, p2, true);
-        Port port3 = new DefaultPort(dev1, p3, false);
-        Port port4 = new DefaultPort(dev1, p4, true);
-        Port port5 = new DefaultPort(dev1, p5, true);
-        List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
-        expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
-        replay(deviceService);
-        assertFalse(rrp.noMoreEnabledPort(devId1, v10));
-        assertTrue(rrp.noMoreEnabledPort(devId1, v20));
-        assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
-    }
-
-    // Disable port 1 to 3
-    @Test
-    public void testNoMoreEnabledPortCase4() throws Exception {
-        Port port1 = new DefaultPort(dev1, p1, false);
-        Port port2 = new DefaultPort(dev1, p2, false);
-        Port port3 = new DefaultPort(dev1, p3, false);
-        Port port4 = new DefaultPort(dev1, p4, true);
-        Port port5 = new DefaultPort(dev1, p5, true);
-        List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
-        expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
-        replay(deviceService);
-        assertTrue(rrp.noMoreEnabledPort(devId1, v10));
-        assertTrue(rrp.noMoreEnabledPort(devId1, v20));
-        assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
-    }
-
-    // Disable port 1 to 4
-    @Test
-    public void testNoMoreEnabledPortCase5() throws Exception {
-        Port port1 = new DefaultPort(dev1, p1, false);
-        Port port2 = new DefaultPort(dev1, p2, false);
-        Port port3 = new DefaultPort(dev1, p3, false);
-        Port port4 = new DefaultPort(dev1, p4, false);
-        Port port5 = new DefaultPort(dev1, p5, true);
-        List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
-        expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
-        replay(deviceService);
-        assertTrue(rrp.noMoreEnabledPort(devId1, v10));
-        assertTrue(rrp.noMoreEnabledPort(devId1, v20));
-        assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
-    }
-
-    // Disable all ports
-    @Test
-    public void testNoMoreEnabledPortCase6() throws Exception {
-        Port port1 = new DefaultPort(dev1, p1, false);
-        Port port2 = new DefaultPort(dev1, p2, false);
-        Port port3 = new DefaultPort(dev1, p3, false);
-        Port port4 = new DefaultPort(dev1, p4, false);
-        Port port5 = new DefaultPort(dev1, p5, false);
-        List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
-        expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
-        replay(deviceService);
-        assertTrue(rrp.noMoreEnabledPort(devId1, v10));
-        assertTrue(rrp.noMoreEnabledPort(devId1, v20));
-        assertTrue(rrp.noMoreEnabledPort(devId1, vInt));
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/TestUtils.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/TestUtils.java
deleted file mode 100644
index 339b2c8..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/TestUtils.java
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Copyright 2019-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.Lists;
-import com.google.common.collect.Sets;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ICMPEcho;
-
-import java.util.Map;
-import java.util.Set;
-
-import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
-import static org.onlab.packet.ICMP6.ECHO_REQUEST;
-import static org.onlab.packet.IPv4.PROTOCOL_ICMP;
-import static org.onosproject.routeservice.Route.Source.STATIC;
-
-/**
- * Utilities class for unit tests.
- */
-public final class TestUtils {
-
-    private TestUtils() {
-
-    }
-
-    // Device configuration section
-    static final DeviceId REMOTE_LEAF = DeviceId.deviceId("of:0000000000000001");
-    static final int REMOTE_LEAF_SID4 = 1;
-    static final String REMOTE_LEAF_LB4 = "192.168.0.1";
-    static final int REMOTE_LEAF_SID6 = 10;
-    static final String REMOTE_LEAF_LB6 = "2000::c0a8:1";
-    private static final PortNumber P1 = PortNumber.portNumber(1);
-    static final MacAddress REMOTE_MAC = MacAddress.valueOf("00:00:00:00:00:02");
-
-    static final DeviceId LOCAL_LEAF = DeviceId.deviceId("of:0000000000000101");
-    static final int LOCAL_LEAF_SID4 = 101;
-    static final String LOCAL_LEAF_LB4 = "192.168.0.101";
-    static final int LOCAL_LEAF_SID6 = 111;
-    static final String LOCAL_LEAF_LB6 = "2000::c0a8:101";
-    static final MacAddress LOCAL_MAC = MacAddress.valueOf("00:00:00:00:01:01");
-
-    // Configure a pair
-    static final DeviceId LOCAL_LEAF1 = DeviceId.deviceId("of:0000000000000201");
-    static final int LOCAL_LEAF1_SID4 = 201;
-    static final String LOCAL_LEAF1_LB4 = "192.168.0.201";
-    static final int LOCAL_LEAF1_SID6 = 211;
-    static final String LOCAL_LEAF1_LB6 = "2000::c0a8:201";
-    static final MacAddress LOCAL_MAC1 = MacAddress.valueOf("00:00:00:00:02:01");
-
-    static final DeviceId LOCAL_LEAF2 = DeviceId.deviceId("of:0000000000000202");
-    static final int LOCAL_LEAF2_SID4 = 202;
-    static final String LOCAL_LEAF2_LB4 = "192.168.0.202";
-    static final int LOCAL_LEAF2_SID6 = 212;
-    static final String LOCAL_LEAF2_LB6 = "2000::c0a8:202";
-    static final MacAddress LOCAL_MAC2 = MacAddress.valueOf("00:00:00:00:02:02");
-
-    // Pair port
-    static final PortNumber P3 = PortNumber.portNumber(3);
-
-    // Ports configuration section
-    static final ConnectPoint CP11 = new ConnectPoint(REMOTE_LEAF, P1);
-    private static final PortNumber P2 = PortNumber.portNumber(2);
-    static final ConnectPoint CP12 = new ConnectPoint(REMOTE_LEAF, P2);
-    private static final IpAddress IP4_1 = IpAddress.valueOf("10.0.0.254");
-    private static final IpPrefix PREFIX4_1 = IpPrefix.valueOf("10.0.0.254/24");
-    private static final IpAddress IP6_1 = IpAddress.valueOf("2000::ff");
-    private static final IpPrefix PREFIX6_1 = IpPrefix.valueOf("2000::ff/120");
-    private static final InterfaceIpAddress INTF_IP4_1 = new InterfaceIpAddress(
-            IP4_1, PREFIX4_1);
-    private static final InterfaceIpAddress INTF_IP6_1 = new InterfaceIpAddress(
-            IP6_1, PREFIX6_1);
-    private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
-    static final Interface INTF1 = new Interface(
-            "INTF1", CP12, Lists.newArrayList(INTF_IP4_1, INTF_IP6_1), MacAddress.NONE,
-            null, INTF_VLAN_UNTAGGED, null, null);
-    static final ConnectPoint CP13 = new ConnectPoint(REMOTE_LEAF, P3);
-    private static final IpAddress IP4_2 = IpAddress.valueOf("10.0.3.254");
-    private static final IpPrefix PREFIX4_2 = IpPrefix.valueOf("10.0.3.254/24");
-    private static final IpAddress IP6_2 = IpAddress.valueOf("2000::3ff");
-    private static final IpPrefix PREFIX6_2 = IpPrefix.valueOf("2000::3ff/120");
-    private static final InterfaceIpAddress INTF_IP4_2 = new InterfaceIpAddress(
-            IP4_2, PREFIX4_2);
-    private static final InterfaceIpAddress INTF_IP6_2 = new InterfaceIpAddress(
-            IP6_2, PREFIX6_2);
-    static final Interface INTF2 = new Interface(
-            "INTF2", CP13, Lists.newArrayList(INTF_IP4_2, INTF_IP6_2), MacAddress.NONE,
-            null, INTF_VLAN_UNTAGGED, null, null);
-
-    static final ConnectPoint CP1011 = new ConnectPoint(LOCAL_LEAF, P1);
-    private static final IpAddress IP4_11 = IpAddress.valueOf("10.0.1.254");
-    private static final IpPrefix PREFIX4_11 = IpPrefix.valueOf("10.0.1.254/24");
-    private static final InterfaceIpAddress INTF_IP4_11 = new InterfaceIpAddress(
-            IP4_11, PREFIX4_11);
-    private static final IpAddress IP6_11 = IpAddress.valueOf("2000::1ff");
-    private static final IpPrefix PREFIX6_11 = IpPrefix.valueOf("2000::1ff/120");
-    private static final InterfaceIpAddress INTF_IP6_11 = new InterfaceIpAddress(
-            IP6_11, PREFIX6_11);
-    static final Interface INTF111 = new Interface(
-            "INTF111", CP1011, Lists.newArrayList(INTF_IP4_11, INTF_IP6_11), MacAddress.NONE, null,
-            INTF_VLAN_UNTAGGED, null, null);
-
-    static final ConnectPoint CP2011 = new ConnectPoint(LOCAL_LEAF1, P1);
-    private static final IpAddress IP4_21 = IpAddress.valueOf("10.0.2.254");
-    private static final IpPrefix PREFIX4_21 = IpPrefix.valueOf("10.0.2.254/24");
-    private static final InterfaceIpAddress INTF_IP4_21 = new InterfaceIpAddress(
-            IP4_21, PREFIX4_21);
-    private static final IpAddress IP6_21 = IpAddress.valueOf("2000::2ff");
-    private static final IpPrefix PREFIX6_21 = IpPrefix.valueOf("2000::2ff/120");
-    private static final InterfaceIpAddress INTF_IP6_21 = new InterfaceIpAddress(
-            IP6_21, PREFIX6_21);
-    static final Interface INTF211 = new Interface(
-            "INTF211", CP2011, Lists.newArrayList(INTF_IP4_21, INTF_IP6_21), MacAddress.NONE, null,
-            INTF_VLAN_UNTAGGED, null, null);
-
-    static final ConnectPoint CP2021 = new ConnectPoint(LOCAL_LEAF2, P1);
-    private static final IpAddress IP4_22 = IpAddress.valueOf("10.0.2.254");
-    private static final IpPrefix PREFIX4_22 = IpPrefix.valueOf("10.0.2.254/24");
-    private static final InterfaceIpAddress INTF_IP4_22 = new InterfaceIpAddress(
-            IP4_22, PREFIX4_22);
-    private static final IpAddress IP6_22 = IpAddress.valueOf("2000::2ff");
-    private static final IpPrefix PREFIX6_22 = IpPrefix.valueOf("2000::2ff/120");
-    private static final InterfaceIpAddress INTF_IP6_22 = new InterfaceIpAddress(
-            IP6_22, PREFIX6_22);
-    static final Interface INTF212 = new Interface(
-            "INTF212", CP2021, Lists.newArrayList(INTF_IP4_22, INTF_IP6_22), MacAddress.NONE, null,
-            INTF_VLAN_UNTAGGED, null, null);
-    private static final PortNumber P4 = PortNumber.portNumber(4);
-    static final ConnectPoint CP2024 = new ConnectPoint(LOCAL_LEAF2, P4);
-    private static final PortNumber P5 = PortNumber.portNumber(5);
-    static final ConnectPoint CP2025 = new ConnectPoint(LOCAL_LEAF2, P5);
-    private static final IpAddress IP4_23 = IpAddress.valueOf("10.0.4.254");
-    private static final IpPrefix PREFIX4_23 = IpPrefix.valueOf("10.0.4.254/24");
-    private static final InterfaceIpAddress INTF_IP4_23 = new InterfaceIpAddress(
-            IP4_23, PREFIX4_23);
-    private static final IpAddress IP6_23 = IpAddress.valueOf("2000::4ff");
-    private static final IpPrefix PREFIX6_23 = IpPrefix.valueOf("2000::4ff/120");
-    private static final InterfaceIpAddress INTF_IP6_23 = new InterfaceIpAddress(
-            IP6_23, PREFIX6_23);
-    static final Interface INTF213 = new Interface(
-            "INTF212", CP2024, Lists.newArrayList(INTF_IP4_23, INTF_IP6_23), MacAddress.NONE, null,
-            INTF_VLAN_UNTAGGED, null, null);
-
-    // Packet-ins section
-    private static final MacAddress SRC_MAC = MacAddress.valueOf("00:00:00:00:00:01");
-
-    private static final ICMPEcho ICMP_ECHO = new ICMPEcho()
-            .setIdentifier((short) 0)
-            .setSequenceNum((short) 0);
-
-    private static final ICMP ICMP_REQUEST = (ICMP) new ICMP()
-            .setIcmpType(TYPE_ECHO_REQUEST)
-            .setPayload(ICMP_ECHO);
-
-    private static final Ip4Address SRC_IPV4 = Ip4Address.valueOf("10.0.1.1");
-    static final Ip4Address DST_IPV4 = Ip4Address.valueOf("10.0.0.254");
-
-    private static final IPv4 IPV4_REQUEST = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4.toInt())
-            .setSourceAddress(SRC_IPV4.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV4 = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV4_REQUEST);
-
-    private static final ICMP6 ICMP6_REQUEST = new ICMP6()
-            .setIcmpType(ECHO_REQUEST);
-
-    private static final Ip6Address SRC_IPV6 = Ip6Address.valueOf("2000::101");
-    static final Ip6Address DST_IPV6 = Ip6Address.valueOf("2000::ff");
-
-    private static final IPv6 IPV6_REQUEST = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6.toOctets())
-            .setSourceAddress(SRC_IPV6.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6 = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV6_REQUEST);
-
-    static final Ip4Address SRC_IPV41 = Ip4Address.valueOf("10.0.2.1");
-
-    private static final IPv4 IPV41_REQUEST = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4.toInt())
-            .setSourceAddress(SRC_IPV41.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV41 = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV41_REQUEST);
-
-    static final Ip6Address SRC_IPV61 = Ip6Address.valueOf("2000::201");
-
-    private static final IPv6 IPV61_REQUEST = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6.toOctets())
-            .setSourceAddress(SRC_IPV61.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV61 = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV61_REQUEST);
-
-    private static final MacAddress SRC_MAC_MY = MacAddress.valueOf("00:01:00:00:00:01");
-    static final Ip4Address SRC_IPV4_MY = Ip4Address.valueOf("10.0.0.1");
-
-    private static final IPv4 IPV4_REQUEST_MY = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4.toInt())
-            .setSourceAddress(SRC_IPV4_MY.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV4_MY = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC_MY)
-            .setPayload(IPV4_REQUEST_MY);
-
-    static final Ip6Address SRC_IPV6_MY = Ip6Address.valueOf("2000::1");
-
-    private static final IPv6 IPV6_REQUEST_MY = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6.toOctets())
-            .setSourceAddress(SRC_IPV6_MY.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6_MY = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC_MY)
-            .setPayload(IPV6_REQUEST_MY);
-
-    static final Ip4Address DST_IPV4_LOCAL = Ip4Address.valueOf("10.0.3.254");
-
-    private static final IPv4 IPV4_REQUEST_LOCAL = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4_LOCAL.toInt())
-            .setSourceAddress(SRC_IPV4_MY.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV4_LOCAL = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC_MY)
-            .setPayload(IPV4_REQUEST_LOCAL);
-
-    static final Ip6Address DST_IPV6_LOCAL = Ip6Address.valueOf("2000::3ff");
-
-    private static final IPv6 IPV6_REQUEST_LOCAL = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6_LOCAL.toOctets())
-            .setSourceAddress(SRC_IPV6_MY.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6_LOCAL = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC_MY)
-            .setPayload(IPV6_REQUEST_LOCAL);
-
-    static final Ip4Address DST_IPV4_SAME = Ip4Address.valueOf("10.0.4.254");
-
-    private static final IPv4 IPV4_REQUEST_SAME = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4_SAME.toInt())
-            .setSourceAddress(SRC_IPV41.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV4_SAME = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(LOCAL_MAC2)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV4_REQUEST_SAME);
-
-    static final Ip6Address DST_IPV6_SAME = Ip6Address.valueOf("2000::4ff");
-
-    private static final IPv6 IPV6_REQUEST_SAME = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6_SAME.toOctets())
-            .setSourceAddress(SRC_IPV61.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6_SAME = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(LOCAL_MAC2)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV6_REQUEST_SAME);
-
-    static final Ip6Address DST_IPV6_LL = Ip6Address.valueOf(
-            IPv6.getLinkLocalAddress(MacAddress.NONE.toBytes()));
-    static final Ip6Address SRC_IPV6_LL = Ip6Address.valueOf(
-            IPv6.getLinkLocalAddress(SRC_MAC_MY.toBytes()));
-
-    private static final IPv6 IPV6_REQUEST_LL = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6_LL.toOctets())
-            .setSourceAddress(SRC_IPV6_LL.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6_LL = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(MacAddress.NONE)
-            .setSourceMACAddress(SRC_MAC_MY)
-            .setPayload(IPV6_REQUEST_LL);
-
-    static final Ip4Address DST_IPV4_LOOPBACK = Ip4Address.valueOf(REMOTE_LEAF_LB4);
-
-    private static final IPv4 IPV4_REQUEST_LOOPBACK = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4_LOOPBACK.toInt())
-            .setSourceAddress(SRC_IPV4_MY.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV4_LOOPBACK = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC_MY)
-            .setPayload(IPV4_REQUEST_LOOPBACK);
-
-    static final Ip6Address DST_IPV6_LOOPBACK = Ip6Address.valueOf(REMOTE_LEAF_LB6);
-
-    private static final IPv6 IPV6_REQUEST_LOOPBACK = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6_LOOPBACK.toOctets())
-            .setSourceAddress(SRC_IPV6_MY.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6_LOOPBACK = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(REMOTE_MAC)
-            .setSourceMACAddress(SRC_MAC_MY)
-            .setPayload(IPV6_REQUEST_LOOPBACK);
-
-    static final Ip4Address DST_IPV4_LOOPBACK_PAIR = Ip4Address.valueOf(LOCAL_LEAF1_LB4);
-
-    private static final IPv4 IPV4_REQUEST_LOOPBACK_PAIR = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4_LOOPBACK_PAIR.toInt())
-            .setSourceAddress(SRC_IPV41.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV4_LOOPBACK_PAIR = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(LOCAL_MAC1)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV4_REQUEST_LOOPBACK_PAIR);
-
-    static final Ip6Address DST_IPV6_LOOPBACK_PAIR = Ip6Address.valueOf(LOCAL_LEAF2_LB6);
-
-    private static final IPv6 IPV6_REQUEST_LOOPBACK_PAIR = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6_LOOPBACK_PAIR.toOctets())
-            .setSourceAddress(SRC_IPV61.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6_LOOPBACK_PAIR = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(LOCAL_MAC2)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV6_REQUEST_LOOPBACK_PAIR);
-
-    static final Ip4Address DST_IPV4_GATEWAY_PAIR = Ip4Address.valueOf("10.0.2.254");
-
-    private static final IPv4 IPV4_REQUEST_GATEWAY_PAIR = (IPv4) new IPv4()
-            .setDestinationAddress(DST_IPV4_GATEWAY_PAIR.toInt())
-            .setSourceAddress(SRC_IPV41.toInt())
-            .setTtl((byte) 64)
-            .setProtocol(PROTOCOL_ICMP)
-            .setPayload(ICMP_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV4_GATEWAY_PAIR = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV4)
-            .setDestinationMACAddress(LOCAL_MAC1)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV4_REQUEST_GATEWAY_PAIR);
-
-    static final Ip6Address DST_IPV6_GATEWAY_PAIR = Ip6Address.valueOf("2000::2ff");
-
-    private static final IPv6 IPV6_REQUEST_GATEWAY_PAIR = (IPv6) new IPv6()
-            .setDestinationAddress(DST_IPV6_GATEWAY_PAIR.toOctets())
-            .setSourceAddress(SRC_IPV61.toOctets())
-            .setHopLimit((byte) 255)
-            .setNextHeader(IPv6.PROTOCOL_ICMP6)
-            .setPayload(ICMP6_REQUEST);
-
-    static final Ethernet ETH_REQ_IPV6_GATEWAY_PAIR = (Ethernet) new Ethernet()
-            .setEtherType(Ethernet.TYPE_IPV6)
-            .setDestinationMACAddress(LOCAL_MAC2)
-            .setSourceMACAddress(SRC_MAC)
-            .setPayload(IPV6_REQUEST_GATEWAY_PAIR);
-
-    // Resolved route
-    private static final ResolvedRoute IPV4_ROUTE = new ResolvedRoute(
-            new Route(STATIC, SRC_IPV4.toIpPrefix(), SRC_IPV4), MacAddress.NONE);
-    private static final ResolvedRoute IPV6_ROUTE = new ResolvedRoute(
-            new Route(STATIC, SRC_IPV6.toIpPrefix(), SRC_IPV6), MacAddress.NONE);
-    static final Map<IpPrefix, Set<ResolvedRoute>> ROUTE_STORE = ImmutableMap.of(SRC_IPV4.toIpPrefix(),
-                                                                                 Sets.newHashSet(IPV4_ROUTE),
-                                                                                 SRC_IPV6.toIpPrefix(),
-                                                                                 Sets.newHashSet(IPV6_ROUTE));
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/BlockedPortsConfigTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/BlockedPortsConfigTest.java
deleted file mode 100644
index e457896..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/BlockedPortsConfigTest.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright 2017-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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.DefaultApplicationId;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-/**
- * Unit tests for {@link BlockedPortsConfig}.
- */
-public class BlockedPortsConfigTest {
-
-    private static final ApplicationId APP_ID = new DefaultApplicationId(1, "foo");
-    private static final String KEY = "blocked";
-    private static final ObjectMapper MAPPER = new ObjectMapper();
-
-    private static final String DEV1 = "of:0000000000000001";
-    private static final String DEV2 = "of:0000000000000002";
-    private static final String DEV3 = "of:0000000000000003";
-    private static final String DEV4 = "of:0000000000000004";
-    private static final String RANGE_14 = "1-4";
-    private static final String RANGE_79 = "7-9";
-    private static final String P1 = "1";
-    private static final String P5 = "5";
-    private static final String P9 = "9";
-
-    private BlockedPortsConfig cfg;
-    private BlockedPortsConfig.Range range;
-
-    private void print(String s) {
-        System.out.println(s);
-    }
-
-    private void print(Object o) {
-        print(o.toString());
-    }
-
-    @Before
-    public void setUp() throws IOException {
-        InputStream blockedPortsJson = BlockedPortsConfigTest.class
-                .getResourceAsStream("/blocked-ports.json");
-        JsonNode node = MAPPER.readTree(blockedPortsJson);
-        cfg = new BlockedPortsConfig();
-        cfg.init(APP_ID, KEY, node, MAPPER, null);
-    }
-
-    @Test
-    public void basic() {
-        cfg = new BlockedPortsConfig();
-        print(cfg);
-
-        assertEquals("non-empty devices list", 0, cfg.deviceIds().size());
-        assertEquals("non-empty port-ranges list", 0, cfg.portRanges("non-exist").size());
-    }
-
-
-    @Test
-    public void overIteratePort() {
-        Iterator<Long> iterator = cfg.portIterator(DEV3);
-        while (iterator.hasNext()) {
-            print(iterator.next());
-        }
-
-        try {
-            print(iterator.next());
-            fail("NoSuchElement exception NOT thrown");
-        } catch (NoSuchElementException e) {
-            print("<good> " + e);
-        }
-    }
-
-    @Test
-    public void overIterateRange() {
-        range = new BlockedPortsConfig.Range("4-6");
-
-        Iterator<Long> iterator = range.iterator();
-        while (iterator.hasNext()) {
-            print(iterator.next());
-        }
-
-        try {
-            print(iterator.next());
-            fail("NoSuchElement exception NOT thrown");
-        } catch (NoSuchElementException e) {
-            print("<good> " + e);
-        }
-    }
-
-
-    @Test
-    public void simple() {
-        List<String> devIds = cfg.deviceIds();
-        print(devIds);
-        assertEquals("wrong dev id count", 3, devIds.size());
-        assertEquals("missing dev 1", true, devIds.contains(DEV1));
-        assertEquals("dev 2??", false, devIds.contains(DEV2));
-        assertEquals("missing dev 3", true, devIds.contains(DEV3));
-
-        List<String> d1ranges = cfg.portRanges(DEV1);
-        print(d1ranges);
-        assertEquals("wrong d1 range count", 2, d1ranges.size());
-        assertEquals("missing 1-4", true, d1ranges.contains(RANGE_14));
-        assertEquals("missing 7-9", true, d1ranges.contains(RANGE_79));
-
-        List<String> d2ranges = cfg.portRanges(DEV2);
-        print(d2ranges);
-        assertEquals("wrong d2 range count", 0, d2ranges.size());
-
-        List<String> d3ranges = cfg.portRanges(DEV3);
-        print(d3ranges);
-        assertEquals("wrong d3 range count", 1, d3ranges.size());
-        assertEquals("range 1-4?", false, d3ranges.contains(RANGE_14));
-        assertEquals("missing 7-9", true, d3ranges.contains(RANGE_79));
-    }
-
-
-    private void verifyPorts(List<Long> ports, long... exp) {
-        assertEquals("Wrong port count", exp.length, ports.size());
-        for (long e : exp) {
-            assertEquals("missing port", true, ports.contains(e));
-        }
-    }
-
-    private void verifyPortIterator(String devid, long... exp) {
-        List<Long> ports = new ArrayList<>();
-        Iterator<Long> iter = cfg.portIterator(devid);
-        iter.forEachRemaining(ports::add);
-        print(ports);
-        verifyPorts(ports, exp);
-    }
-
-    @Test
-    public void rangeIterators() {
-        verifyPortIterator(DEV1, 1, 2, 3, 4, 7, 8, 9);
-        verifyPortIterator(DEV2);
-        verifyPortIterator(DEV3, 7, 8, 9);
-    }
-
-    @Test
-    public void singlePorts() {
-        List<String> devIds = cfg.deviceIds();
-        print(devIds);
-        assertEquals("wrong dev id count", 3, devIds.size());
-        assertEquals("missing dev 4", true, devIds.contains(DEV4));
-
-        List<String> d1ranges = cfg.portRanges(DEV4);
-        print(d1ranges);
-        assertEquals("wrong d4 range count", 3, d1ranges.size());
-        assertEquals("missing 1", true, d1ranges.contains(P1));
-        assertEquals("missing 5", true, d1ranges.contains(P5));
-        assertEquals("missing 9", true, d1ranges.contains(P9));
-
-        verifyPortIterator(DEV4, 1, 5, 9);
-    }
-
-
-    // test Range inner class
-
-    @Test
-    public void rangeBadFormat() {
-        try {
-            range = new BlockedPortsConfig.Range("not-a-range-format");
-            fail("no exception thrown");
-        } catch (IllegalArgumentException iar) {
-            print(iar);
-            assertEquals("wrong msg", "Bad Range Format not-a-range-format", iar.getMessage());
-        }
-    }
-
-    @Test
-    public void rangeBadHi() {
-        try {
-            range = new BlockedPortsConfig.Range("2-nine");
-            fail("no exception thrown");
-        } catch (IllegalArgumentException iar) {
-            print(iar);
-            assertEquals("wrong msg", "Bad Range Format 2-nine", iar.getMessage());
-        }
-    }
-
-    @Test
-    public void rangeHiLessThanLo() {
-        try {
-            range = new BlockedPortsConfig.Range("9-5");
-            fail("no exception thrown");
-        } catch (IllegalArgumentException iar) {
-            print(iar);
-            assertEquals("wrong msg", "Bad Range Format 9-5", iar.getMessage());
-        }
-    }
-
-    @Test
-    public void rangeNegative() {
-        try {
-            range = new BlockedPortsConfig.Range("-2-4");
-            fail("no exception thrown");
-        } catch (IllegalArgumentException iar) {
-            print(iar);
-            assertEquals("wrong msg", "Bad Range Format -2-4", iar.getMessage());
-        }
-    }
-
-    @Test
-    public void rangeGood() {
-        range = new BlockedPortsConfig.Range("100-104");
-        List<Long> values = new ArrayList<>();
-        range.iterator().forEachRemaining(values::add);
-        print(values);
-        verifyPorts(values, 100, 101, 102, 103, 104);
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java
deleted file mode 100644
index 1674f6c..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2019-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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.net.neighbour.NeighbourResolutionService;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-
-import java.io.InputStream;
-import java.util.List;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.*;
-
-public class DeviceConfigurationTest {
-    private static final DeviceId DEV1 = DeviceId.deviceId("of:1");
-    private static final String CONFIG_KEY = "segmentrouting";
-    private static final PortNumber PORT1 = PortNumber.portNumber(1);
-    private static final PortNumber PORT2 = PortNumber.portNumber(2);
-    private static final ConnectPoint CP1 = new ConnectPoint(DEV1, PORT1);
-    private static final ConnectPoint CP2 = new ConnectPoint(DEV1, PORT2);
-    private static final MacAddress MAC1 = MacAddress.valueOf("00:11:22:33:44:55");
-    private static final VlanId VLAN1 = VlanId.vlanId((short) 10);
-    private static final VlanId VLAN2 = VlanId.vlanId((short) 20);
-    private static final IpPrefix PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
-    private static final IpPrefix PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
-    private static final IpPrefix ROUTE1 = IpPrefix.valueOf("20.0.1.254/24");
-    private static final InterfaceIpAddress INTF1_IP = new InterfaceIpAddress(PREFIX1.address(), PREFIX1);
-    private static final InterfaceIpAddress INTF2_IP = new InterfaceIpAddress(PREFIX2.address(), PREFIX2);
-    private static final List<InterfaceIpAddress> IP_LIST1 = Lists.newArrayList(INTF1_IP);
-    private static final List<InterfaceIpAddress> IP_LIST2 = Lists.newArrayList(INTF2_IP);
-    private static final Interface INTF1 = new Interface("mock-intf1", CP1, IP_LIST1, MAC1,
-            null, VLAN1, null, null);
-    private static final Interface INTF2 = new Interface("mock-intf2", CP2, IP_LIST2, MAC1,
-            null, VLAN2, null, null);
-    private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF1, INTF2);
-
-    private DeviceConfiguration devConfig;
-
-    private NetworkConfigRegistry networkConfigService;
-
-    @Before
-    public void setUp() throws Exception {
-        InterfaceService interfaceService;
-        networkConfigService = null;
-        NeighbourResolutionService neighbourResolutionService;
-        SegmentRoutingManager srManager;
-
-        // Mock device netcfg
-        InputStream jsonStream = SegmentRoutingDeviceConfigTest.class.getResourceAsStream("/device.json");
-        ObjectMapper mapper = new ObjectMapper();
-        JsonNode jsonNode = mapper.readTree(jsonStream);
-        SegmentRoutingDeviceConfig srDevConfig = new SegmentRoutingDeviceConfig();
-        srDevConfig.init(DEV1, CONFIG_KEY, jsonNode, mapper, config -> { });
-        BasicDeviceConfig basicDeviceConfig = new BasicDeviceConfig();
-        basicDeviceConfig.init(DEV1, DEV1.toString(), JsonNodeFactory.instance.objectNode(), mapper, config -> { });
-        BasicDeviceConfig purgeOnDisconnectConfig = basicDeviceConfig.purgeOnDisconnection(true);
-
-
-        // Mock interface netcfg
-        jsonStream = InterfaceConfig.class.getResourceAsStream("/interface1.json");
-        jsonNode = mapper.readTree(jsonStream);
-        InterfaceConfig interfaceConfig1 = new InterfaceConfig();
-        interfaceConfig1.init(CP1, CONFIG_KEY, jsonNode, mapper, config -> { });
-        jsonStream = InterfaceConfig.class.getResourceAsStream("/interface2.json");
-        jsonNode = mapper.readTree(jsonStream);
-        InterfaceConfig interfaceConfig2 = new InterfaceConfig();
-        interfaceConfig2.init(CP1, CONFIG_KEY, jsonNode, mapper, config -> { });
-
-        networkConfigService = createMock(NetworkConfigRegistry.class);
-        expect(networkConfigService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class))
-                .andReturn(Sets.newHashSet(DEV1)).anyTimes();
-        expect(networkConfigService.getConfig(DEV1, SegmentRoutingDeviceConfig.class))
-                .andReturn(srDevConfig).anyTimes();
-        expect(networkConfigService.addConfig(DEV1, BasicDeviceConfig.class))
-                .andReturn(basicDeviceConfig).anyTimes();
-        expect(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class))
-                .andReturn(basicDeviceConfig).anyTimes();
-        expect(networkConfigService.applyConfig(DEV1, BasicDeviceConfig.class, purgeOnDisconnectConfig.node()))
-                .andReturn(purgeOnDisconnectConfig).anyTimes();
-        expect(networkConfigService.getSubjects(ConnectPoint.class, InterfaceConfig.class))
-                .andReturn(Sets.newHashSet(CP1, CP2)).anyTimes();
-        expect(networkConfigService.getConfig(CP1, InterfaceConfig.class)).andReturn(interfaceConfig1).anyTimes();
-        expect(networkConfigService.getConfig(CP2, InterfaceConfig.class)).andReturn(interfaceConfig2).anyTimes();
-        expect(networkConfigService.applyConfig(eq(CP1), eq(InterfaceConfig.class), anyObject()))
-                .andReturn(interfaceConfig1).anyTimes();
-        expect(networkConfigService.applyConfig(eq(CP2), eq(InterfaceConfig.class), anyObject()))
-                .andReturn(interfaceConfig2).anyTimes();
-        expect(networkConfigService.getConfig(null, SegmentRoutingAppConfig.class)).andReturn(null).anyTimes();
-        replay(networkConfigService);
-
-        interfaceService = createMock(InterfaceService.class);
-        expect(interfaceService.getInterfaces()).andReturn(INTERFACES).anyTimes();
-        expect(interfaceService.getInterfacesByPort(CP1)).andReturn(Sets.newHashSet(INTF1)).anyTimes();
-        expect(interfaceService.getInterfacesByPort(CP2)).andReturn(Sets.newHashSet(INTF2)).anyTimes();
-        replay(interfaceService);
-
-        neighbourResolutionService = createMock(NeighbourResolutionService.class);
-        neighbourResolutionService.registerNeighbourHandler(anyObject(ConnectPoint.class), anyObject(), anyObject());
-        expectLastCall().anyTimes();
-        replay(neighbourResolutionService);
-
-        srManager = new SegmentRoutingManager();
-        srManager.interfaceService = interfaceService;
-        srManager.cfgService = networkConfigService;
-        srManager.neighbourResolutionService = neighbourResolutionService;
-
-        devConfig = new DeviceConfiguration(srManager);
-        devConfig.addSubnet(CP2, ROUTE1);
-    }
-
-    @Test
-    public void getConfiguredSubnets() {
-        Set<IpPrefix> expect = Sets.newHashSet(PREFIX1, PREFIX2);
-        assertEquals(expect, devConfig.getConfiguredSubnets(DEV1));
-    }
-
-    @Test
-    public void getSubnets() {
-        Set<IpPrefix> expect = Sets.newHashSet(PREFIX1, PREFIX2, ROUTE1);
-        assertEquals(expect, devConfig.getSubnets(DEV1));
-    }
-
-    @Test
-    public void getPortSubnets() {
-        assertEquals(Sets.newHashSet(PREFIX1), devConfig.getPortSubnets(DEV1, PORT1));
-        assertEquals(Sets.newHashSet(PREFIX2), devConfig.getPortSubnets(DEV1, PORT2));
-    }
-
-    @Test
-    public void inSameSubnet() {
-        assertTrue(devConfig.inSameSubnet(DEV1, PREFIX1.address()));
-        assertTrue(devConfig.inSameSubnet(DEV1, PREFIX2.address()));
-        assertFalse(devConfig.inSameSubnet(DEV1, ROUTE1.address()));
-    }
-
-    @Test
-    public void getPurgeOnDisconnect() {
-        assertNotNull(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class));
-        assertTrue(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class).purgeOnDisconnection());
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java
deleted file mode 100644
index 2a10f56..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright 2016-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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.TestApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-
-import java.io.InputStream;
-import java.util.Set;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.*;
-
-/**
- * Tests for class {@link SegmentRoutingAppConfig}.
- */
-public class SegmentRoutingAppConfigTest {
-    private SegmentRoutingAppConfig config;
-    private SegmentRoutingAppConfig invalidConfig;
-    private SegmentRoutingAppConfig mplsEcmpConfig;
-
-    private static final MacAddress ROUTER_MAC_1 = MacAddress.valueOf("00:00:00:00:00:01");
-    private static final MacAddress ROUTER_MAC_2 = MacAddress.valueOf("00:00:00:00:00:02");
-    private static final MacAddress ROUTER_MAC_3 = MacAddress.valueOf("00:00:00:00:00:03");
-    private static final ConnectPoint PORT_1 = ConnectPoint.deviceConnectPoint("of:1/1");
-    private static final ConnectPoint PORT_2 = ConnectPoint.deviceConnectPoint("of:1/2");
-    private static final ConnectPoint PORT_3 = ConnectPoint.deviceConnectPoint("of:1/3");
-    private static final DeviceId VROUTER_ID_1 = DeviceId.deviceId("of:1");
-    private static final DeviceId VROUTER_ID_2 = DeviceId.deviceId("of:2");
-    private static final String PROVIDER_1 = "org.onosproject.provider.host";
-    private static final String PROVIDER_2 = "org.onosproject.netcfghost";
-    private static final String PROVIDER_3 = "org.onosproject.anotherprovider";
-    private static final IpPrefix BLACKHOLE_IP = IpPrefix.valueOf("10.0.0.0/8");
-    private static final IpPrefix BLACKHOLE_IP_2 = IpPrefix.valueOf("20.0.0.0/8");
-
-    /**
-     * Initialize test related variables.
-     *
-     * @throws Exception
-     */
-    @Before
-    public void setUp() throws Exception {
-        InputStream jsonStream = SegmentRoutingAppConfigTest.class
-                .getResourceAsStream("/app.json");
-        InputStream invalidJsonStream = SegmentRoutingAppConfigTest.class
-                .getResourceAsStream("/app-invalid.json");
-        InputStream mplsEcmpJsonStream = SegmentRoutingAppConfigTest.class
-                .getResourceAsStream("/app-ecmp.json");
-
-        String key = SegmentRoutingManager.APP_NAME;
-        ApplicationId subject = new TestApplicationId(key);
-        ObjectMapper mapper = new ObjectMapper();
-        JsonNode jsonNode = mapper.readTree(jsonStream);
-        JsonNode invalidJsonNode = mapper.readTree(invalidJsonStream);
-        JsonNode mplsEcmpJsonNode = mapper.readTree(mplsEcmpJsonStream);
-        ConfigApplyDelegate delegate = new MockDelegate();
-
-        config = new SegmentRoutingAppConfig();
-        config.init(subject, key, jsonNode, mapper, delegate);
-        invalidConfig = new SegmentRoutingAppConfig();
-        invalidConfig.init(subject, key, invalidJsonNode, mapper, delegate);
-        mplsEcmpConfig = new SegmentRoutingAppConfig();
-        mplsEcmpConfig.init(subject, key, mplsEcmpJsonNode, mapper, delegate);
-    }
-
-    /**
-     * Tests config validity.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testIsValid() throws Exception {
-        assertTrue(config.isValid());
-        assertFalse(invalidConfig.isValid());
-        assertTrue(mplsEcmpConfig.isValid());
-    }
-
-    /**
-     * Test MPLS-ECMP default getter. By-default
-     * MPLS-ECMPS is false.
-     */
-    @Test
-    public void testDefaultMplsEcmp() {
-        boolean mplsEcmp = config.mplsEcmp();
-        assertThat(mplsEcmp, is(false));
-    }
-
-    /**
-     * Test MPLS-ECMP getter.
-     */
-    @Test
-    public void testMplsEcmp() {
-        boolean mplsEcmp = mplsEcmpConfig.mplsEcmp();
-        assertThat(mplsEcmp, is(true));
-    }
-
-    /**
-     * Test MPLS-ECMP setter.
-     */
-    @Test
-    public void testSetMplsEcmp() {
-        /*
-         * In the config the value is not set.
-         */
-        boolean mplsEcmp = config.mplsEcmp();
-        assertThat(mplsEcmp, is(false));
-        config.setMplsEcmp(true);
-        mplsEcmp = config.mplsEcmp();
-        assertThat(mplsEcmp, is(true));
-        /*
-         * In the mplsEcmpConfig the value is true,
-         */
-        mplsEcmp = mplsEcmpConfig.mplsEcmp();
-        assertThat(mplsEcmp, is(true));
-        config.setMplsEcmp(false);
-        mplsEcmp = config.mplsEcmp();
-        assertThat(mplsEcmp, is(false));
-    }
-
-    /**
-     * Tests vRouterMacs getter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testVRouterMacs() throws Exception {
-        Set<MacAddress> vRouterMacs = config.vRouterMacs();
-        assertNotNull("vRouterMacs should not be null", vRouterMacs);
-        assertThat(vRouterMacs.size(), is(2));
-        assertTrue(vRouterMacs.contains(ROUTER_MAC_1));
-        assertTrue(vRouterMacs.contains(ROUTER_MAC_2));
-    }
-
-    /**
-     * Tests vRouterMacs setter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSetVRouterMacs() throws Exception {
-        ImmutableSet.Builder<MacAddress> builder = ImmutableSet.builder();
-        builder.add(ROUTER_MAC_3);
-        config.setVRouterMacs(builder.build());
-
-        Set<MacAddress> vRouterMacs = config.vRouterMacs();
-        assertThat(vRouterMacs.size(), is(1));
-        assertTrue(vRouterMacs.contains(ROUTER_MAC_3));
-    }
-
-    /**
-     * Tests suppressSubnet getter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSuppressSubnet() throws Exception {
-        Set<ConnectPoint> suppressSubnet = config.suppressSubnet();
-        assertNotNull("suppressSubnet should not be null", suppressSubnet);
-        assertThat(suppressSubnet.size(), is(2));
-        assertTrue(suppressSubnet.contains(PORT_1));
-        assertTrue(suppressSubnet.contains(PORT_2));
-    }
-
-    /**
-     * Tests suppressSubnet setter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSetSuppressSubnet() throws Exception {
-        ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
-        builder.add(PORT_3);
-        config.setSuppressSubnet(builder.build());
-
-        Set<ConnectPoint> suppressSubnet = config.suppressSubnet();
-        assertNotNull("suppressSubnet should not be null", suppressSubnet);
-        assertThat(suppressSubnet.size(), is(1));
-        assertTrue(suppressSubnet.contains(PORT_3));
-    }
-
-    /**
-     * Tests suppressHostByPort getter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSuppressHostByPort() throws Exception {
-        Set<ConnectPoint> suppressHostByPort = config.suppressHostByPort();
-        assertNotNull("suppressHostByPort should not be null", suppressHostByPort);
-        assertThat(suppressHostByPort.size(), is(2));
-        assertTrue(suppressHostByPort.contains(PORT_1));
-        assertTrue(suppressHostByPort.contains(PORT_2));
-    }
-
-    /**
-     * Tests suppressHostByPort setter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSetSuppressHostByPort() throws Exception {
-        ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
-        builder.add(PORT_3);
-        config.setSuppressHostByPort(builder.build());
-
-        Set<ConnectPoint> suppressHostByPort = config.suppressHostByPort();
-        assertNotNull("suppressHostByPort should not be null", suppressHostByPort);
-        assertThat(suppressHostByPort.size(), is(1));
-        assertTrue(suppressHostByPort.contains(PORT_3));
-    }
-
-    /**
-     * Tests suppressHostByProvider getter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSuppressHostByProvider() throws Exception {
-        Set<String> supprsuppressHostByProvider = config.suppressHostByProvider();
-        assertNotNull("suppressHostByProvider should not be null", supprsuppressHostByProvider);
-        assertThat(supprsuppressHostByProvider.size(), is(2));
-        assertTrue(supprsuppressHostByProvider.contains(PROVIDER_1));
-        assertTrue(supprsuppressHostByProvider.contains(PROVIDER_2));
-    }
-
-    /**
-     * Tests suppressHostByProvider setter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSetHostLearning() throws Exception {
-        ImmutableSet.Builder<String> builder = ImmutableSet.builder();
-        builder.add(PROVIDER_3);
-        config.setSuppressHostByProvider(builder.build());
-
-        Set<String> supprsuppressHostByProvider = config.suppressHostByProvider();
-        assertNotNull("suppressHostByProvider should not be null", supprsuppressHostByProvider);
-        assertThat(supprsuppressHostByProvider.size(), is(1));
-        assertTrue(supprsuppressHostByProvider.contains(PROVIDER_3));
-    }
-
-    /**
-     * Tests BlackHoleIps getter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testBlackHoleIps() throws Exception {
-        Set<IpPrefix> blackHoleIps = config.blackholeIPs();
-        assertNotNull("BlackHoleIps should not be null", blackHoleIps);
-        assertThat(blackHoleIps.size(), is(1));
-        assertTrue(blackHoleIps.contains(BLACKHOLE_IP));
-    }
-
-    /**
-     * Tests BlackHoleIps setter.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testSetBlackHoleIps() throws Exception {
-
-        config.setBalckholeIps(ImmutableSet.of(BLACKHOLE_IP_2));
-
-        Set<IpPrefix> blackHoleIps = config.blackholeIPs();
-        assertThat(blackHoleIps.size(), is(1));
-        assertTrue(blackHoleIps.contains(BLACKHOLE_IP_2));
-    }
-
-    private class MockDelegate implements ConfigApplyDelegate {
-        @Override
-        public void onApply(Config config) {
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java
deleted file mode 100644
index ddf90bb..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2016-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.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.ConfigApplyDelegate;
-
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests for class {@link SegmentRoutingDeviceConfig}.
- */
-public class SegmentRoutingDeviceConfigTest {
-    private SegmentRoutingDeviceConfig config;
-    private SegmentRoutingDeviceConfig ipv6Config;
-    private SegmentRoutingDeviceConfig pairConfig;
-    private SegmentRoutingDeviceConfig invalidConfig;
-    private Map<Integer, Set<Integer>> adjacencySids1;
-    private Map<Integer, Set<Integer>> adjacencySids2;
-    private static final DeviceId PAIR_DEVICE_ID = DeviceId.deviceId("of:123456789ABCDEF0");
-    private static final PortNumber PAIR_LOCAL_PORT = PortNumber.portNumber(10);
-
-    @Before
-    public void setUp() throws Exception {
-        InputStream jsonStream = SegmentRoutingDeviceConfigTest.class
-                .getResourceAsStream("/device.json");
-        InputStream ipv6JsonStream = SegmentRoutingDeviceConfigTest.class
-                .getResourceAsStream("/device-ipv6.json");
-        InputStream pairJsonStream = SegmentRoutingDeviceConfigTest.class
-                .getResourceAsStream("/device-pair.json");
-        InputStream invalidJsonStream = SegmentRoutingDeviceConfigTest.class
-                .getResourceAsStream("/device-invalid.json");
-
-        adjacencySids1 = new HashMap<>();
-        Set<Integer> ports1 = new HashSet<>();
-        ports1.add(2);
-        ports1.add(3);
-        adjacencySids1.put(100, ports1);
-        Set<Integer> ports2 = new HashSet<>();
-        ports2.add(4);
-        ports2.add(5);
-        adjacencySids1.put(200, ports2);
-
-        adjacencySids2 = new HashMap<>();
-        Set<Integer> ports3 = new HashSet<>();
-        ports3.add(6);
-        adjacencySids2.put(300, ports3);
-
-        DeviceId subject = DeviceId.deviceId("of:0000000000000001");
-        String key = "segmentrouting";
-        ObjectMapper mapper = new ObjectMapper();
-        JsonNode jsonNode = mapper.readTree(jsonStream);
-        JsonNode ipv6JsonNode = mapper.readTree(ipv6JsonStream);
-        JsonNode pairJsonNode = mapper.readTree(pairJsonStream);
-        JsonNode invalidJsonNode = mapper.readTree(invalidJsonStream);
-        ConfigApplyDelegate delegate = new MockDelegate();
-
-        config = new SegmentRoutingDeviceConfig();
-        config.init(subject, key, jsonNode, mapper, delegate);
-
-        ipv6Config = new SegmentRoutingDeviceConfig();
-        ipv6Config.init(subject, key, ipv6JsonNode, mapper, delegate);
-
-        pairConfig = new SegmentRoutingDeviceConfig();
-        pairConfig.init(subject, key, pairJsonNode, mapper, delegate);
-
-        invalidConfig = new SegmentRoutingDeviceConfig();
-        invalidConfig.init(subject, key, invalidJsonNode, mapper, delegate);
-    }
-
-    @Test
-    public void testIsValid() {
-        assertTrue(config.isValid());
-        assertTrue(ipv6Config.isValid());
-        assertTrue(pairConfig.isValid());
-        assertFalse(invalidConfig.isValid());
-    }
-
-    @Test
-    public void testName() throws Exception {
-        assertTrue(config.name().isPresent());
-        assertThat(config.name().get(), is("Leaf-R1"));
-    }
-
-    @Test
-    public void testSetName() throws Exception {
-        config.setName("Spine-R1");
-        assertTrue(config.name().isPresent());
-        assertThat(config.name().get(), is("Spine-R1"));
-    }
-
-    @Test
-    public void testRouterIp() throws Exception {
-        assertThat(config.routerIpv4(), is(IpAddress.valueOf("10.0.1.254")));
-        assertThat(ipv6Config.routerIpv4(), is(IpAddress.valueOf("10.0.1.254")));
-        assertThat(ipv6Config.routerIpv6(), is(IpAddress.valueOf("2000::c0a8:0101")));
-    }
-
-    @Test
-    public void testSetRouterIp() throws Exception {
-        config.setRouterIpv4("10.0.2.254");
-        assertThat(config.routerIpv4(), is(IpAddress.valueOf("10.0.2.254")));
-        ipv6Config.setRouterIpv4("10.0.2.254");
-        assertThat(ipv6Config.routerIpv4(), is(IpAddress.valueOf("10.0.2.254")));
-        ipv6Config.setRouterIpv6("2000::c0a9:0101");
-        assertThat(ipv6Config.routerIpv6(), is(IpAddress.valueOf("2000::c0a9:0101")));
-    }
-
-    @Test
-    public void testRouterMac() throws Exception {
-        assertThat(config.routerMac(), is(MacAddress.valueOf("00:00:00:00:01:80")));
-    }
-
-    @Test
-    public void testSetRouterMac() throws Exception {
-        config.setRouterMac("00:00:00:00:02:80");
-        assertThat(config.routerMac(), is(MacAddress.valueOf("00:00:00:00:02:80")));
-    }
-
-    @Test
-    public void testNodeSid() throws Exception {
-        assertThat(config.nodeSidIPv4(), is(101));
-        assertThat(ipv6Config.nodeSidIPv4(), is(101));
-        assertThat(ipv6Config.nodeSidIPv6(), is(111));
-    }
-
-    @Test
-    public void testSetNodeSid() throws Exception {
-        config.setNodeSidIPv4(200);
-        assertThat(config.nodeSidIPv4(), is(200));
-        ipv6Config.setNodeSidIPv4(200);
-        assertThat(ipv6Config.nodeSidIPv4(), is(200));
-        ipv6Config.setNodeSidIPv6(201);
-        assertThat(ipv6Config.nodeSidIPv6(), is(201));
-    }
-
-    @Test
-    public void testIsEdgeRouter() throws Exception {
-        assertThat(config.isEdgeRouter(), is(true));
-    }
-
-    @Test
-    public void testSetIsEdgeRouter() throws Exception {
-        config.setIsEdgeRouter(false);
-        assertThat(config.isEdgeRouter(), is(false));
-    }
-
-    @Test
-    public void testAdjacencySids() throws Exception {
-        assertThat(config.adjacencySids(), is(adjacencySids1));
-    }
-
-    @Test
-    public void testSetAdjacencySids() throws Exception {
-        config.setAdjacencySids(adjacencySids2);
-        assertThat(config.adjacencySids(), is(adjacencySids2));
-    }
-
-    @Test
-    public void testPairDeviceId() throws Exception {
-        assertNull(config.pairDeviceId());
-        assertNull(ipv6Config.pairDeviceId());
-        assertThat(pairConfig.pairDeviceId(), is(PAIR_DEVICE_ID));
-    }
-
-    @Test
-    public void testSetPairDeviceId() throws Exception {
-        config.setPairDeviceId(PAIR_DEVICE_ID);
-        assertThat(config.pairDeviceId(), is(PAIR_DEVICE_ID));
-    }
-
-    @Test
-    public void testPairLocalPort() throws Exception {
-        assertNull(config.pairLocalPort());
-        assertNull(ipv6Config.pairLocalPort());
-        assertThat(pairConfig.pairLocalPort(), is(PAIR_LOCAL_PORT));
-    }
-
-    @Test
-    public void testSetPairLocalPort() throws Exception {
-        config.setPairLocalPort(PAIR_LOCAL_PORT);
-        assertThat(config.pairLocalPort(), is(PAIR_LOCAL_PORT));
-    }
-
-    private class MockDelegate implements ConfigApplyDelegate {
-        @Override
-        public void onApply(Config configFile) {
-        }
-    }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/grouphandler/DestinationSetTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/grouphandler/DestinationSetTest.java
deleted file mode 100644
index b41fe07..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/grouphandler/DestinationSetTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2017-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.grouphandler;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.net.DeviceId;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class DestinationSetTest {
-    DestinationSet ds1, ds2, ds3, ds4, ds5, ds6;
-    DeviceId d201, d202;
-    int el201, el202;
-
-    @Before
-    public void setUp() {
-        d201 = DeviceId.deviceId("of:0000000000000201");
-        d202 = DeviceId.deviceId("of:0000000000000202");
-        el201 = 201;
-        el202 = 202;
-        ds1 = DestinationSet.createTypePushNone(d201);
-        ds2 = DestinationSet.createTypePushBos(el201, d201);
-        ds3 = DestinationSet.createTypePushBos(el201, d201, el202, d202);
-        ds4 = DestinationSet.createTypePushBos(DestinationSet.NO_EDGE_LABEL, d201,
-                                               DestinationSet.NO_EDGE_LABEL, d202);
-        ds5 = DestinationSet.createTypePopNotBos(d201);
-        ds6 = DestinationSet.createTypeSwapBos(el201, d201);
-    }
-
-    @Test
-    public void testIsValid() {
-        assertTrue(!ds1.notBos());
-        assertTrue(!ds1.swap());
-        assertTrue(ds1.getEdgeLabel(d201) == DestinationSet.NO_EDGE_LABEL);
-        assertTrue(ds1.getDestinationSwitches().size() == 1);
-
-        assertTrue(!ds2.notBos());
-        assertTrue(!ds2.swap());
-        assertTrue(ds2.getEdgeLabel(d201) == el201);
-        assertTrue(ds2.getDestinationSwitches().size() == 1);
-
-        assertTrue(!ds3.notBos());
-        assertTrue(!ds3.swap());
-        assertTrue(ds3.getEdgeLabel(d201) == el201);
-        assertTrue(ds3.getEdgeLabel(d202) == el202);
-        assertTrue(ds3.getDestinationSwitches().size() == 2);
-
-        assertTrue(!ds4.notBos());
-        assertTrue(!ds4.swap());
-        assertTrue(ds4.getEdgeLabel(d201) == DestinationSet.NO_EDGE_LABEL);
-        assertTrue(ds4.getEdgeLabel(d202) == DestinationSet.NO_EDGE_LABEL);
-        assertTrue(ds4.getDestinationSwitches().size() == 2);
-
-        assertFalse(ds1.equals(ds2));
-        assertFalse(ds1.equals(ds4));
-        assertFalse(ds3.equals(ds4));
-        assertFalse(ds2.equals(ds3));
-        assertFalse(ds1.equals(ds3));
-
-        assertFalse(ds1.equals(ds5));
-        assertFalse(ds2.equals(ds6));
-    }
-
-
-    @Test
-    public void testOneDestinationWithoutLabel() {
-        DestinationSet testds = DestinationSet.createTypePushNone(d201);
-        assertTrue(testds.equals(ds1)); // match
-
-        testds = DestinationSet.createTypePopNotBos(d201);
-        assertFalse(testds.equals(ds1)); // wrong notBos
-        assertTrue(testds.equals(ds5)); // correct notBos
-
-        testds = DestinationSet.createTypePushNone(d202);
-        assertFalse(testds.equals(ds1)); //wrong device
-
-        testds = DestinationSet.createTypePushBos(el201, d201);
-        assertFalse(testds.equals(ds1)); // wrong label
-
-        testds = DestinationSet.createTypePushBos(-1, d201, -1, d202);
-        assertFalse(testds.equals(ds1)); // 2-devs should not match
-
-        testds = DestinationSet.createTypeSwapBos(el201, d201);
-        assertFalse(testds.equals(ds1)); // wrong type and label
-        assertTrue(testds.equals(ds6)); // correct swap
-
-        testds = DestinationSet.createTypeSwapNotBos(el201, d201);
-        assertFalse(testds.equals(ds6)); // wrong notbos
-    }
-
-
-
-    @Test
-    public void testOneDestinationWithLabel() {
-        DestinationSet testds = DestinationSet.createTypePushBos(203, d202);
-        assertFalse(testds.equals(ds2)); //wrong label
-
-        testds = DestinationSet.createTypePushBos(201, d202);
-        assertFalse(testds.equals(ds2)); //wrong device
-
-        testds = DestinationSet.createTypePushBos(201,  DeviceId.deviceId("of:0000000000000201"));
-        assertTrue(testds.equals(ds2)); // match
-
-        testds = DestinationSet.createTypePushNone(d201);
-        assertFalse(testds.equals(ds2)); // wrong label
-
-        testds = DestinationSet.createTypePushBos(el201, d201, el202, d202);
-        assertFalse(testds.equals(ds1)); // 2-devs should not match
-    }
-
-    @Test
-    public void testDestPairWithLabel() {
-        DestinationSet testds = DestinationSet.createTypePushBos(el201, d201, el202, d202);
-        assertTrue(testds.equals(ds3)); // match same switches, same order
-        assertTrue(testds.hashCode() == ds3.hashCode());
-
-        testds = DestinationSet.createTypePushBos(el202, d202, el201, d201);
-        assertTrue(testds.equals(ds3)); // match same switches, order reversed
-        assertTrue(testds.hashCode() == ds3.hashCode());
-
-        testds = DestinationSet.createTypePushBos(el202, d202);
-        assertFalse(testds.equals(ds3)); // one less switch should not match
-        assertFalse(testds.hashCode() == ds3.hashCode());
-
-        testds = DestinationSet.createTypePushBos(el201, d201);
-        assertFalse(testds.equals(ds3)); // one less switch should not match
-        assertFalse(testds.hashCode() == ds3.hashCode());
-
-        testds = DestinationSet.createTypePushBos(el201, d201, 0, DeviceId.NONE);
-        assertFalse(testds.equals(ds3)); // one less switch should not match
-        assertFalse(testds.hashCode() == ds3.hashCode());
-
-        testds = DestinationSet.createTypePushBos(el201, d202, el201, d201);
-        assertFalse(testds.equals(ds3)); // wrong labels
-        assertFalse(testds.hashCode() == ds3.hashCode());
-
-        testds = DestinationSet.createTypePushBos(el202, d202, el201, d202);
-        assertFalse(testds.equals(ds3)); // wrong device
-        assertFalse(testds.hashCode() == ds3.hashCode());
-
-        testds = DestinationSet.createTypePushBos(
-                                    el202, DeviceId.deviceId("of:0000000000000205"),
-                                    el201, d201);
-        assertFalse(testds.equals(ds3)); // wrong device
-        assertFalse(testds.hashCode() == ds3.hashCode());
-    }
-
-    @Test
-    public void testDestPairWithoutLabel() {
-        DestinationSet testds = DestinationSet.createTypePushBos(-1, d201, -1, d202);
-        assertTrue(testds.equals(ds4)); // match same switches, same order
-        assertTrue(testds.hashCode() == ds4.hashCode());
-
-        testds = DestinationSet.createTypePushBos(-1, d202, -1, d201);
-        assertTrue(testds.equals(ds4)); // match same switches, order reversed
-        assertTrue(testds.hashCode() == ds4.hashCode());
-
-        testds = DestinationSet.createTypePushBos(-1, d202);
-        assertFalse(testds.equals(ds4)); // one less switch should not match
-        assertFalse(testds.hashCode() == ds4.hashCode());
-
-        testds = DestinationSet.createTypePushBos(-1, d201);
-        assertFalse(testds.equals(ds4)); // one less switch should not match
-        assertFalse(testds.hashCode() == ds4.hashCode());
-
-        testds = DestinationSet.createTypePushBos(-1, d201, 0, DeviceId.NONE);
-        assertFalse(testds.equals(ds4)); // one less switch should not match
-        assertFalse(testds.hashCode() == ds4.hashCode());
-
-        testds = DestinationSet.createTypePushBos(el201, d201, -1, d202);
-        assertFalse(testds.equals(ds4)); // wrong labels
-        assertFalse(testds.hashCode() == ds4.hashCode());
-
-        testds = DestinationSet.createTypePushBos(-1, d202, -1, d202);
-        assertFalse(testds.equals(ds4)); // wrong device
-        assertFalse(testds.hashCode() == ds4.hashCode());
-
-        testds = DestinationSet.createTypePushBos(
-                                    -1, DeviceId.deviceId("of:0000000000000205"),
-                                    -1, d201);
-        assertFalse(testds.equals(ds4)); // wrong device
-        assertFalse(testds.hashCode() == ds4.hashCode());
-    }
-
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/pwaas/PwaasUtilTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/pwaas/PwaasUtilTest.java
deleted file mode 100644
index 1d9f07e..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/pwaas/PwaasUtilTest.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2018-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.pwaas;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.onlab.junit.TestUtils;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.segmentrouting.MockDevice;
-
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-public class PwaasUtilTest {
-    private static final DeviceId DID1 = DeviceId.deviceId("of:1");
-    private static final DeviceId DID2 = DeviceId.deviceId("of:2");
-    private static final DeviceId DID99 = DeviceId.deviceId("of:99");
-    private static final PortNumber PN1 = PortNumber.portNumber(1);
-    private static final PortNumber PN2 = PortNumber.portNumber(2);
-    private static final PortNumber PN99 = PortNumber.portNumber(99);
-    private static final ConnectPoint CP11 = new ConnectPoint(DID1, PN1);
-    private static final ConnectPoint CP12 = new ConnectPoint(DID1, PN2);
-    private static final ConnectPoint CP21 = new ConnectPoint(DID2, PN1);
-    private static final ConnectPoint CP22 = new ConnectPoint(DID2, PN2);
-    private static final VlanId V1 = VlanId.vlanId((short) 1);
-    private static final VlanId V2 = VlanId.vlanId((short) 2);
-    private static final Device D1 = new MockDevice(DID1, null);
-    private static final Device D2 = new MockDevice(DID2, null);
-    private static final Port P11 = new DefaultPort(D1, PN1, true);
-    private static final Port P12 = new DefaultPort(D1, PN2, true);
-    private static final Port P21 = new DefaultPort(D2, PN1, true);
-    private static final Port P22 = new DefaultPort(D2, PN2, true);
-    private static final Interface I11 = new Interface("I11", CP11, Lists.newArrayList(), MacAddress.NONE,
-            VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
-    private static final Interface I12 = new Interface("I12", CP12, Lists.newArrayList(), MacAddress.NONE,
-            VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
-    private static final Interface I21 = new Interface("I21", CP21, Lists.newArrayList(), MacAddress.NONE,
-            VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
-    private static final Interface I22 = new Interface("I22", CP22, Lists.newArrayList(), MacAddress.NONE,
-            VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
-
-    private ConnectPoint cp1;
-    private ConnectPoint cp2;
-    private VlanId ingressInner;
-    private VlanId ingressOuter;
-    private VlanId egressInner;
-    private VlanId egressOuter;
-    private static final Long TUNNEL_ID = (long) 1234;
-
-    @Before
-    public void setUp() {
-        DeviceService deviceService = createNiceMock(DeviceService.class);
-        InterfaceService intfService = createNiceMock(InterfaceService.class);
-        TestUtils.setField(PwaasUtil.class, "deviceService", deviceService);
-        TestUtils.setField(PwaasUtil.class, "intfService", intfService);
-
-        expect(deviceService.getDevice(DID1)).andReturn(D1).anyTimes();
-        expect(deviceService.getDevice(DID2)).andReturn(D2).anyTimes();
-        expect(deviceService.getPort(CP11)).andReturn(P11).anyTimes();
-        expect(deviceService.getPort(CP12)).andReturn(P12).anyTimes();
-        expect(deviceService.getPort(CP21)).andReturn(P21).anyTimes();
-        expect(deviceService.getPort(CP22)).andReturn(P22).anyTimes();
-        expect(intfService.getInterfacesByPort(CP11)).andReturn(Sets.newHashSet(I11)).anyTimes();
-        expect(intfService.getInterfacesByPort(CP12)).andReturn(Sets.newHashSet(I12)).anyTimes();
-        expect(intfService.getInterfacesByPort(CP21)).andReturn(Sets.newHashSet(I21)).anyTimes();
-        expect(intfService.getInterfacesByPort(CP22)).andReturn(Sets.newHashSet(I22)).anyTimes();
-        replay(deviceService);
-        replay(intfService);
-    }
-
-    @Rule
-    public final ExpectedException exception = ExpectedException.none();
-
-    @Test
-    public void verifyPolicy() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = V2;
-        egressInner = V1;
-        egressOuter = V2;
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-
-        ingressInner = VlanId.NONE;
-        ingressOuter = VlanId.NONE;
-        egressInner = VlanId.NONE;
-        egressOuter = VlanId.NONE;
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyOnSameDevice() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID1, PN2);
-        ingressInner = VlanId.NONE;
-        ingressOuter = VlanId.NONE;
-        egressInner = VlanId.NONE;
-        egressOuter = VlanId.NONE;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_SAME_DEV, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyEmptyInnerCp1() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = VlanId.NONE;
-        ingressOuter = V1;
-        egressInner = VlanId.NONE;
-        egressOuter = VlanId.NONE;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_EMPTY_INNER_WHEN_OUTER_PRESENT, TUNNEL_ID, "cp1"));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyEmptyInnerCp2() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = VlanId.NONE;
-        ingressOuter = VlanId.NONE;
-        egressInner = VlanId.NONE;
-        egressOuter = V1;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_EMPTY_INNER_WHEN_OUTER_PRESENT, TUNNEL_ID, "cp2"));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyVlanWildcard() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = VlanId.ANY;
-        ingressOuter = VlanId.NONE;
-        egressInner = VlanId.NONE;
-        egressOuter = VlanId.NONE;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_WILDCARD_VLAN, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-
-    @Test
-    public void verifyPolicyDeviceServiceNotAvailable() {
-        TestUtils.setField(PwaasUtil.class, "deviceService", null);
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = V2;
-        egressInner = V1;
-        egressOuter = V2;
-        exception.expect(IllegalStateException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_SERVICE_UNAVAIL, "DeviceService"));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyDoubleToUntagged() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = V2;
-        egressInner = VlanId.NONE;
-        egressOuter = VlanId.NONE;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_DOUBLE_TO_UNTAGGED, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyDoubleToSingle() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = V2;
-        egressInner = V1;
-        egressOuter = VlanId.NONE;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_DOUBLE_TO_SINGLE, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicySingleToUntagged() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = VlanId.NONE;
-        egressInner = VlanId.NONE;
-        egressOuter = VlanId.NONE;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_SINGLE_TO_UNTAGGED, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyVlanTranslation() {
-        cp1 = new ConnectPoint(DID1, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = VlanId.NONE;
-        egressInner = V2;
-        egressOuter = VlanId.NONE;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_VLAN_TRANSLATION, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyDeviceNotFound() {
-        cp1 = new ConnectPoint(DID99, PN1);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = V2;
-        egressInner = V1;
-        egressOuter = V2;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_DEV_NOT_FOUND, DID99, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-
-    @Test
-    public void verifyPolicyPortNotFound() {
-        cp1 = new ConnectPoint(DID1, PN99);
-        cp2 = new ConnectPoint(DID2, PN2);
-        ingressInner = V1;
-        ingressOuter = V2;
-        egressInner = V1;
-        egressOuter = V2;
-        exception.expect(IllegalArgumentException.class);
-        exception.expectMessage(String.format(PwaasUtil.ERR_PORT_NOT_FOUND, PN99, DID1, TUNNEL_ID));
-        PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodecTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodecTest.java
deleted file mode 100644
index bac9ff4..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodecTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2019-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.xconnect.api;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.VlanId;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import org.onosproject.codec.impl.MockCodecContext;
-import org.onosproject.net.DeviceId;
-
-import java.io.InputStream;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
-public class XconnectCodecTest {
-    private static final DeviceId DEVICE_ID = DeviceId.deviceId("of:1");
-    private static final VlanId VLAN_VID = VlanId.vlanId((short) 10);
-    private static final XconnectKey KEY = new XconnectKey(DEVICE_ID, VLAN_VID);
-    private static final XconnectEndpoint EP1 = XconnectEndpoint.fromString("1");
-    private static final XconnectEndpoint EP2 = XconnectEndpoint.fromString("2");
-    private static final XconnectEndpoint EP3 = XconnectEndpoint.fromString("LB:5");
-
-    private CodecContext context;
-    private JsonCodec<XconnectDesc> codec;
-
-    @Before
-    public void setUp() throws Exception {
-        context = new MockCodecContext();
-        codec = new XconnectCodec();
-    }
-
-    @Test
-    public void testEncodePort() throws Exception {
-        Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP2);
-        XconnectDesc desc1 = new XconnectDesc(KEY, endpoints1);
-
-        ObjectMapper mapper = new ObjectMapper();
-        InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect1.json");
-        JsonNode expected = mapper.readTree(jsonStream1);
-
-        JsonNode actual = codec.encode(desc1, context);
-
-        assertEquals(expected.get(XconnectCodec.DEVICE_ID), actual.get(XconnectCodec.DEVICE_ID));
-        assertEquals(expected.get(XconnectCodec.VLAN_ID).asInt(), actual.get(XconnectCodec.VLAN_ID).asInt());
-        assertEquals(expected.get(XconnectCodec.ENDPOINTS), actual.get(XconnectCodec.ENDPOINTS));
-    }
-
-    @Test
-    public void testDecodePort() throws Exception {
-        Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP2);
-        XconnectDesc expected = new XconnectDesc(KEY, endpoints1);
-
-        ObjectMapper mapper = new ObjectMapper();
-        InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect1.json");
-        ObjectNode objectNode = mapper.readTree(jsonStream1).deepCopy();
-
-        XconnectDesc actual = codec.decode(objectNode, context);
-
-        assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testEncodeLb() throws Exception {
-        Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP3);
-        XconnectDesc desc1 = new XconnectDesc(KEY, endpoints1);
-
-        ObjectMapper mapper = new ObjectMapper();
-        InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect2.json");
-        JsonNode expected = mapper.readTree(jsonStream1);
-
-        JsonNode actual = codec.encode(desc1, context);
-
-        assertEquals(expected.get(XconnectCodec.DEVICE_ID), actual.get(XconnectCodec.DEVICE_ID));
-        assertEquals(expected.get(XconnectCodec.VLAN_ID).asInt(), actual.get(XconnectCodec.VLAN_ID).asInt());
-        assertEquals(expected.get(XconnectCodec.ENDPOINTS), actual.get(XconnectCodec.ENDPOINTS));
-    }
-
-    @Test
-    public void testDecodeLb() throws Exception {
-        Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP3);
-        XconnectDesc expected = new XconnectDesc(KEY, endpoints1);
-
-        ObjectMapper mapper = new ObjectMapper();
-        InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect2.json");
-        ObjectNode objectNode = mapper.readTree(jsonStream1).deepCopy();
-
-        XconnectDesc actual = codec.decode(objectNode, context);
-
-        assertEquals(expected, actual);
-    }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/resources/app-ecmp.json b/apps/segmentrouting/app/src/test/resources/app-ecmp.json
deleted file mode 100644
index e94b1c5..0000000
--- a/apps/segmentrouting/app/src/test/resources/app-ecmp.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "vRouterMacs" : [
-      "00:00:00:00:00:01",
-      "00:00:00:00:00:02"
-  ],
-  "suppressSubnet" : [
-      "of:1/1",
-      "of:1/2"
-  ],
-  "suppressHostByPort" : [
-      "of:1/1",
-      "of:1/2"
-  ],
-  "suppressHostByProvider" : [
-      "org.onosproject.provider.host",
-      "org.onosproject.netcfghost"
-  ],
-  "MPLS-ECMP" : true
-}
diff --git a/apps/segmentrouting/app/src/test/resources/app-invalid.json b/apps/segmentrouting/app/src/test/resources/app-invalid.json
deleted file mode 100644
index 01508f8..0000000
--- a/apps/segmentrouting/app/src/test/resources/app-invalid.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "vRouterMacs" : [
-      "00:00:00:00:00:01",
-      "00:00:00:00:00:02"
-  ],
-  "suppressSubnet" : [
-      "of:1/1",
-      "of:1/2"
-  ],
-  "suppressHostByPort" : [
-      "of:1/1",
-      "wrongPort"
-  ],
-  "suppressHostByProvider" : []
-}
diff --git a/apps/segmentrouting/app/src/test/resources/app.json b/apps/segmentrouting/app/src/test/resources/app.json
deleted file mode 100644
index 2e59b0d..0000000
--- a/apps/segmentrouting/app/src/test/resources/app.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "vRouterMacs" : [
-      "00:00:00:00:00:01",
-      "00:00:00:00:00:02"
-  ],
-  "suppressSubnet" : [
-      "of:1/1",
-      "of:1/2"
-  ],
-  "suppressHostByPort" : [
-      "of:1/1",
-      "of:1/2"
-  ],
-  "suppressHostByProvider" : [
-      "org.onosproject.provider.host",
-      "org.onosproject.netcfghost"
-  ],
-  "blackholeIps": [
-    "10.0.0.0/8"
-  ]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/blocked-ports-alt.json b/apps/segmentrouting/app/src/test/resources/blocked-ports-alt.json
deleted file mode 100644
index 3d8749e..0000000
--- a/apps/segmentrouting/app/src/test/resources/blocked-ports-alt.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "of:0000000000000001": ["1-9"],
-  "of:0000000000000003": ["7"],
-  "of:0000000000000004": ["1"]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/blocked-ports.json b/apps/segmentrouting/app/src/test/resources/blocked-ports.json
deleted file mode 100644
index 2543f3d..0000000
--- a/apps/segmentrouting/app/src/test/resources/blocked-ports.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "of:0000000000000001": ["1-4", "7-9"],
-  "of:0000000000000003": ["7-9"],
-  "of:0000000000000004": ["1", "5", "9"]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device-invalid.json b/apps/segmentrouting/app/src/test/resources/device-invalid.json
deleted file mode 100644
index dfcbdb8..0000000
--- a/apps/segmentrouting/app/src/test/resources/device-invalid.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "name" : "Leaf-R1",
-  "ipv4NodeSid" : 101,
-  "ipv4Loopback" : "10.0.1.254",
-  "routerMac" : "00:00:00:00:01:80",
-  "isEdgeRouter" : true,
-  "adjacencySids" : [
-    { "adjSid" : 100, "ports" : [2, 3] },
-    { "adjSid" : 200, "ports" : [4, 5] }
-  ],
-  "pairDeviceId" : "of:123456789ABCDEF0"
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device-ipv6.json b/apps/segmentrouting/app/src/test/resources/device-ipv6.json
deleted file mode 100644
index 9832f8c..0000000
--- a/apps/segmentrouting/app/src/test/resources/device-ipv6.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "name" : "Leaf-R1",
-  "ipv4NodeSid" : 101,
-  "ipv4Loopback" : "10.0.1.254",
-  "ipv6NodeSid" : 111,
-  "ipv6Loopback" : "2000::c0a8:0101",
-  "routerMac" : "00:00:00:00:01:80",
-  "isEdgeRouter" : true,
-  "adjacencySids" : [
-    { "adjSid" : 100, "ports" : [2, 3] },
-    { "adjSid" : 200, "ports" : [4, 5] }
-  ]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device-pair.json b/apps/segmentrouting/app/src/test/resources/device-pair.json
deleted file mode 100644
index c699ff5..0000000
--- a/apps/segmentrouting/app/src/test/resources/device-pair.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "name" : "Leaf-R1",
-  "ipv4NodeSid" : 101,
-  "ipv4Loopback" : "10.0.1.254",
-  "routerMac" : "00:00:00:00:01:80",
-  "isEdgeRouter" : true,
-  "adjacencySids" : [
-    { "adjSid" : 100, "ports" : [2, 3] },
-    { "adjSid" : 200, "ports" : [4, 5] }
-  ],
-  "pairDeviceId" : "of:123456789ABCDEF0",
-  "pairLocalPort" : "10"
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device.json b/apps/segmentrouting/app/src/test/resources/device.json
deleted file mode 100644
index 83aec6e..0000000
--- a/apps/segmentrouting/app/src/test/resources/device.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name" : "Leaf-R1",
-  "ipv4NodeSid" : 101,
-  "ipv4Loopback" : "10.0.1.254",
-  "routerMac" : "00:00:00:00:01:80",
-  "isEdgeRouter" : true,
-  "adjacencySids" : [
-    { "adjSid" : 100, "ports" : [2, 3] },
-    { "adjSid" : 200, "ports" : [4, 5] }
-  ]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/interface1.json b/apps/segmentrouting/app/src/test/resources/interface1.json
deleted file mode 100644
index 0f7123f..0000000
--- a/apps/segmentrouting/app/src/test/resources/interface1.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
-  {
-    "ips" : [ "10.0.1.254/24" ],
-    "vlan-untagged": 10
-  }
-]
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/resources/interface2.json b/apps/segmentrouting/app/src/test/resources/interface2.json
deleted file mode 100644
index 114fbf5..0000000
--- a/apps/segmentrouting/app/src/test/resources/interface2.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
-  {
-    "ips" : [ "10.0.2.254/24" ],
-    "vlan-untagged": 20
-  }
-]
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-conflicting-vlan.json b/apps/segmentrouting/app/src/test/resources/pwaas-conflicting-vlan.json
deleted file mode 100644
index fac162d..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-conflicting-vlan.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "1": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000002/2",
-    "cP1InnerTag": "10",
-    "cP1OuterTag": "20",
-    "cP2InnerTag": "11",
-    "cP2OuterTag": "21",
-    "mode": "RAW",
-    "sdTag": "",
-    "pwLabel": "255"
-  },
-  "20": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000002/2",
-    "cP1InnerTag": "100",
-    "cP1OuterTag": "",
-    "cP2InnerTag": "21",
-    "cP2OuterTag": "",
-    "mode": "RAW",
-    "sdTag": "",
-    "pwLabel": "1255"
-  }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-mode.json b/apps/segmentrouting/app/src/test/resources/pwaas-invalid-mode.json
deleted file mode 100644
index af0a9d1..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-mode.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "1": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000011/1",
-    "cP1InnerTag": "10",
-    "cP1OuterTag": "20",
-    "cP2InnerTag": "11",
-    "cP2OuterTag": "",
-    "mode": "UNDEFINED_MODED",
-    "sdTag": "40",
-    "pwLabel": "255"
-  }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-pwlabel.json b/apps/segmentrouting/app/src/test/resources/pwaas-invalid-pwlabel.json
deleted file mode 100644
index 66697f5..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-pwlabel.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "1": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000011/1",
-    "cP1InnerTag": "10",
-    "cP1OuterTag": "20",
-    "cP2InnerTag": "11",
-    "cP2OuterTag": "",
-    "mode": "1",
-    "sdTag": "40",
-    "pwLabel": "255.555551"
-  }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-vlan.json b/apps/segmentrouting/app/src/test/resources/pwaas-invalid-vlan.json
deleted file mode 100644
index b556e06..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-vlan.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "1": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000002/2",
-    "cP1InnerTag": "10",
-    "cP1OuterTag": "20",
-    "cP2InnerTag": "11",
-    "cP2OuterTag": "21",
-    "mode": "RAW",
-    "sdTag": "",
-    "pwLabel": "255"
-  },
-  "20": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000002/2",
-    "cP1InnerTag": "100",
-    "cP1OuterTag": "200.55",
-    "cP2InnerTag": "1100",
-    "cP2OuterTag": "210",
-    "mode": "RAW",
-    "sdTag": "",
-    "pwLabel": "1255"
-  }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas.json b/apps/segmentrouting/app/src/test/resources/pwaas.json
deleted file mode 100644
index 2a58b4e..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "1": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000002/1",
-    "cP1InnerTag": "10",
-    "cP1OuterTag": "20",
-    "cP2InnerTag": "10",
-    "cP2OuterTag": "21",
-    "mode": "RAW",
-    "sdTag": "",
-    "pwLabel": "255"
-  },
-  "20": {
-    "cP1": "of:0000000000000001/1",
-    "cP2": "of:0000000000000002/1",
-    "cP1InnerTag": "100",
-    "cP1OuterTag": "200",
-    "cP2InnerTag": "100",
-    "cP2OuterTag": "210",
-    "mode": "RAW",
-    "sdTag": "",
-    "pwLabel": "1255"
-  }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/xconnect1.json b/apps/segmentrouting/app/src/test/resources/xconnect1.json
deleted file mode 100644
index d8990d4..0000000
--- a/apps/segmentrouting/app/src/test/resources/xconnect1.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "deviceId": "of:1",
-  "vlanId": 10,
-  "endpoints": ["1", "2"]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/xconnect2.json b/apps/segmentrouting/app/src/test/resources/xconnect2.json
deleted file mode 100644
index 61919da..0000000
--- a/apps/segmentrouting/app/src/test/resources/xconnect2.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "deviceId": "of:1",
-  "vlanId": 10,
-  "endpoints": ["1", "LB:5"]
-}
diff --git a/apps/segmentrouting/web/BUILD b/apps/segmentrouting/web/BUILD
deleted file mode 100644
index 67ee7d9..0000000
--- a/apps/segmentrouting/web/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + JACKSON + [
-    "@javax_ws_rs_api//jar",
-    "//utils/rest:onlab-rest",
-    "//apps/segmentrouting/app:onos-apps-segmentrouting-app",
-]
-
-osgi_jar_with_tests(
-    api_description = "REST API for Segment Routing Application",
-    api_package = "org.onosproject.segmentrouting.web",
-    api_title = "Segment Routing Rest Server",
-    api_version = "1.0",
-    web_context = "/onos/segmentrouting",
-    deps = COMPILE_DEPS,
-)
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java
deleted file mode 100644
index 8202eed..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2018-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.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Query multicast trees.
- */
-@Path("mcast")
-public class McastWebResource extends AbstractWebResource {
-
-    private ObjectNode encodeMcastTrees(String gAddr, String source) {
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Set<IpAddress> mcastGroups = ImmutableSet.copyOf(srService.getMcastLeaders(null)
-                                                                 .keySet());
-
-        if (!isNullOrEmpty(gAddr)) {
-            mcastGroups = mcastGroups.stream()
-                    .filter(mcastIp -> mcastIp.equals(IpAddress.valueOf(gAddr)))
-                    .collect(Collectors.toSet());
-        }
-
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode root = mapper.createObjectNode();
-
-        // Print the trees for each group or build json objects
-        mcastGroups.forEach(group -> {
-            // We want to use source cp only for a specific group
-            ConnectPoint sourcecp = null;
-            if (!isNullOrEmpty(source) &&
-                    !isNullOrEmpty(gAddr)) {
-                sourcecp = ConnectPoint.deviceConnectPoint(source);
-            }
-            Multimap<ConnectPoint, List<ConnectPoint>> mcastTree = srService.getMcastTrees(group, sourcecp);
-            // Build a json object for each group
-            root.putPOJO(group.toString(), json(mcastTree));
-
-        });
-        return root;
-    }
-
-    private ObjectNode json(Multimap<ConnectPoint, List<ConnectPoint>> mcastTree) {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode jsonSinks = mapper.createObjectNode();
-        mcastTree.asMap().forEach((sink, paths) -> {
-            ArrayNode jsonPaths = mapper.createArrayNode();
-            paths.forEach(path -> {
-                ArrayNode jsonPath = mapper.createArrayNode();
-                path.forEach(connectPoint -> jsonPath.add(connectPoint.toString()));
-                jsonPaths.addPOJO(jsonPath);
-            });
-            jsonSinks.putPOJO(sink.toString(), jsonPaths);
-        });
-        return jsonSinks;
-    }
-
-    /**
-     * Get all multicast trees.
-     * Returns an object of the multicast trees.
-     *
-     * @return status of OK
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getMcastTrees() {
-        ObjectNode root = encodeMcastTrees(null, null);
-        return ok(root).build();
-    }
-
-    /**
-     * Get the multicast trees of a group.
-     *
-     * @param group group IP address
-     * @return 200 OK with a multicast routes
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("{group}")
-    public Response getRoute(@PathParam("group") String group) {
-        ObjectNode root = encodeMcastTrees(group, null);
-        return ok(root).build();
-    }
-
-    /**
-     * Get the multicast tree of a group.
-     *
-     * @param group group IP address
-     * @param sourcecp source connect point
-     * @return 200 OK with a multicast routes
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("{group}/{sourcecp}")
-    public Response getRoute(@PathParam("group") String group,
-                             @PathParam("sourcecp") String sourcecp) {
-        ObjectNode root = encodeMcastTrees(group, sourcecp);
-        return ok(root).build();
-    }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
deleted file mode 100644
index 0dedc7c..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.web;
-
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Codec of Policy class.
- */
-public final class PolicyCodec extends JsonCodec<Policy> {
-
-    // JSON field names
-    private static final String POLICY_ID = "policy_id";
-    private static final String PRIORITY = "priority";
-    private static final String TYPE = "policy_type";
-    private static final String TUNNEL_ID = "tunnel_id";
-    private static final String DST_IP = "dst_ip";
-    private static final String SRC_IP = "src_ip";
-    private static final String PROTO_TYPE = "proto_type";
-    private static final String SRC_PORT = "src_tp_port";
-    private static final String DST_PORT = "dst_tp_port";
-
-    @Override
-    public ObjectNode encode(Policy policy, CodecContext context) {
-        final ObjectNode result = context.mapper().createObjectNode()
-                .put(POLICY_ID, policy.id());
-
-        result.put(PRIORITY, policy.priority());
-        result.put(TYPE, policy.type().toString());
-
-        if (policy.dstIp() != null) {
-            result.put(DST_IP, policy.dstIp());
-        }
-        if (policy.srcIp() != null) {
-            result.put(SRC_IP, policy.srcIp());
-        }
-        if (policy.ipProto() != null) {
-            result.put(PROTO_TYPE, policy.ipProto());
-        }
-
-        int srcPort = policy.srcPort() & 0xffff;
-        if (policy.srcPort() != 0) {
-            result.put(SRC_PORT, srcPort);
-        }
-        int dstPort = policy.dstPort() & 0xffff;
-        if (policy.dstPort() != 0) {
-            result.put(DST_PORT, dstPort);
-        }
-        if (policy.type() == Policy.Type.TUNNEL_FLOW) {
-            result.put(TUNNEL_ID, ((TunnelPolicy) policy).tunnelId());
-        }
-
-        return result;
-    }
-
-    @Override
-    public Policy decode(ObjectNode json, CodecContext context) {
-
-        String pid = json.path(POLICY_ID).asText();
-        String type = json.path(TYPE).asText();
-        int priority = json.path(PRIORITY).asInt();
-        String dstIp = json.path(DST_IP).asText();
-        String srcIp = json.path(SRC_IP).asText();
-        String tunnelId = json.path(TUNNEL_ID).asText();
-        String protoType = json.path(PROTO_TYPE).asText();
-        short srcPort = json.path(SRC_PORT).shortValue();
-        short dstPort = json.path(DST_PORT).shortValue();
-
-        if (json.path(POLICY_ID).isMissingNode() || pid == null) {
-            // TODO: handle errors
-            return null;
-        }
-
-        TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(pid);
-        if (!json.path(TYPE).isMissingNode() && type != null &&
-                Policy.Type.valueOf(type).equals(Policy.Type.TUNNEL_FLOW)) {
-
-            if (json.path(TUNNEL_ID).isMissingNode() || tunnelId == null) {
-                return null;
-            }
-
-            tpb.setTunnelId(tunnelId);
-            tpb.setType(Policy.Type.valueOf(type));
-
-            if (!json.path(PRIORITY).isMissingNode()) {
-                tpb.setPriority(priority);
-            }
-            if (dstIp != null) {
-                tpb.setDstIp(dstIp);
-            }
-            if (srcIp != null) {
-                tpb.setSrcIp(srcIp);
-            }
-            if (protoType != null) {
-                tpb.setIpProto(protoType);
-            }
-            if (dstPort != 0) {
-                tpb.setDstPort(dstPort);
-            }
-            if (srcPort != 0) {
-                tpb.setSrcPort(srcPort);
-            }
-        }
-
-        return tpb.build();
-    }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
deleted file mode 100644
index 08663e4..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove segment routing plicies.
- */
-// @Path("policy")
-public class PolicyWebResource extends AbstractWebResource {
-
-    private static final PolicyCodec POLICY_CODEC = new PolicyCodec();
-
-    /**
-     * Get all segment routing policies.
-     * Returns an array of segment routing policies.
-     *
-     * @return status of OK
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getPolicy() {
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        List<Policy> policies = srService.getPolicies();
-        ObjectNode result = new ObjectMapper().createObjectNode();
-        result.set("policy", new PolicyCodec().encode(policies, this));
-
-        return ok(result.toString()).build();
-    }
-
-    /**
-     * Create a new segment routing policy.
-     *
-     * @param input JSON stream for policy to create
-     * @return status of the request - OK if the policy is created,
-     * @throws IOException if JSON processing fails
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createPolicy(InputStream input) throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode policyJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Policy policyInfo = POLICY_CODEC.decode(policyJson, this);
-
-        if (policyInfo.type() == Policy.Type.TUNNEL_FLOW) {
-            srService.createPolicy(policyInfo);
-            return Response.ok().build();
-        } else {
-            return Response.serverError().build();
-        }
-    }
-
-    /**
-     * Delete a segment routing policy.
-     *
-     * @param input JSON stream for policy to delete
-     * @return 204 NO CONTENT if the policy is removed
-     * @throws IOException if JSON is invalid
-     */
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response removePolicy(InputStream input) throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode policyJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Policy policyInfo = POLICY_CODEC.decode(policyJson, this);
-        // TODO: Check the result
-        srService.removePolicy(policyInfo);
-
-        return Response.noContent().build();
-    }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
deleted file mode 100644
index b2d5d2f..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.web;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Mode;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
-
-/**
- * Codec of PseudowireCodec class.
- */
-public final class PseudowireCodec extends JsonCodec<DefaultL2TunnelDescription> {
-
-    // JSON field names
-    private static final String PW_ID = "pwId";
-    private static final String CP1 = "cP1";
-    private static final String CP2 = "cP2";
-    private static final String CP1_INNER_TAG = "cP1InnerTag";
-    private static final String CP1_OUTER_TAG = "cP1OuterTag";
-    private static final String CP2_INNER_TAG = "cP2InnerTag";
-    private static final String CP2_OUTER_TAG = "cP2OuterTag";
-    private static final String MODE = "mode";
-    private static final String SERVICE_DELIM_TAG = "serviceTag";
-    private static final String PW_LABEL = "pwLabel";
-
-    // JSON field names for error in return
-    private static final String FAILED_PWS = "failedPws";
-    private static final String FAILED_PW = "pw";
-    private static final String REASON = "reason";
-
-    private static Logger log = LoggerFactory
-            .getLogger(PseudowireCodec.class);
-
-    @Override
-    public ObjectNode encode(DefaultL2TunnelDescription pseudowire, CodecContext context) {
-        final ObjectNode result = context.mapper().createObjectNode()
-                .put(PW_ID, pseudowire.l2Tunnel().tunnelId());
-
-        result.put(CP1, pseudowire.l2TunnelPolicy().cP1().toString());
-        result.put(CP2, pseudowire.l2TunnelPolicy().cP2().toString());
-
-        result.put(CP1_INNER_TAG, pseudowire.l2TunnelPolicy().cP1InnerTag().toString());
-        result.put(CP1_OUTER_TAG, pseudowire.l2TunnelPolicy().cP1OuterTag().toString());
-        result.put(CP2_INNER_TAG, pseudowire.l2TunnelPolicy().cP2InnerTag().toString());
-        result.put(CP2_OUTER_TAG, pseudowire.l2TunnelPolicy().cP2OuterTag().toString());
-        result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
-
-        result.put(MODE, pseudowire.l2Tunnel().pwMode() == L2Mode.RAW ? "RAW" : "TAGGED");
-        result.put(PW_LABEL, pseudowire.l2Tunnel().pwLabel().toString());
-
-        return result;
-    }
-
-    /**
-     * Encoded in an Object Node the pseudowire and the specificError it failed.
-     *
-     * @param failedPW The failed pseudowire
-     * @param specificError The specificError it failed
-     * @param context Our context
-     * @return A node containing the information we provided
-     */
-    public ObjectNode encodeError(DefaultL2TunnelDescription failedPW, String specificError,
-                                          CodecContext context) {
-        ObjectNode result = context.mapper().createObjectNode();
-
-        ObjectNode pw = encode(failedPW, context);
-        result.set(FAILED_PW, pw);
-        result.put(REASON, specificError);
-
-        return result;
-    }
-
-    /**
-     * Encoded in an Object Node the undecoed pseudowire and the specificError it failed.
-     *
-     * @param failedPW The failed pseudowire in json format
-     * @param specificError The specificError it failed
-     * @param context Our context
-     * @return A node containing the information we provided
-     */
-    public ObjectNode encodeError(JsonNode failedPW, String specificError,
-                                  CodecContext context) {
-        ObjectNode result = context.mapper().createObjectNode();
-
-        result.set(FAILED_PW, failedPW);
-        result.put(REASON, specificError);
-
-        return result;
-    }
-
-    /**
-     * Returns a JSON containing the failed pseudowires and the reason that they failed.
-     *
-     * @param failedPws Pairs of pws and reasons.
-     * @param undecodedPws Pairs of pws that we could not decode with reason being illegal arguments.
-     * @param context The context
-     * @return ObjectNode representing the json to return
-     */
-    public ObjectNode encodeFailedPseudowires(
-            List<Pair<DefaultL2TunnelDescription, String>> failedPws,
-            List<Pair<JsonNode, String>> undecodedPws,
-            CodecContext context) {
-
-        ArrayNode failedNodes = context.mapper().createArrayNode();
-        failedPws.stream()
-                .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
-        undecodedPws.stream()
-                .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
-        final ObjectNode toReturn = context.mapper().createObjectNode();
-        toReturn.set(FAILED_PWS, failedNodes);
-        return toReturn;
-    }
-
-    /**
-     *
-     * @param json The json containing the pseudowires.
-     * @param context The context
-     * @return A pair of lists.
-     *         First list contains pseudowires that we were not able to decode
-     *         along with the reason we could not decode them.
-     *         Second list contains successfully decoded pseudowires which we are
-     *         going to instantiate.
-     */
-    public Pair<List<Pair<JsonNode, String>>, List<L2TunnelDescription>> decodePws(ArrayNode json,
-                                                                                   CodecContext context) {
-
-        List<L2TunnelDescription> decodedPws = new ArrayList<>();
-        List<Pair<JsonNode, String>> notDecodedPws = new ArrayList<>();
-        for (JsonNode node : json) {
-            DefaultL2TunnelDescription l2Description;
-            try {
-                l2Description = decode((ObjectNode) node, context);
-                decodedPws.add(l2Description);
-            } catch (IllegalArgumentException e) {
-                // the reason why we could not decode this pseudowire is encoded in the
-                // exception, we need to store it now
-                notDecodedPws.add(Pair.of(node, e.getMessage()));
-            }
-        }
-
-        return Pair.of(notDecodedPws, decodedPws);
-    }
-
-    /**
-     * Decodes a json containg a single field with the pseudowire id.
-     *
-     * @param json Json to decode.
-     * @return The pseudowire id.
-     */
-    public static Integer decodeId(ObjectNode json) {
-
-        Integer id;
-        try {
-            id = parsePwId(json.path(PW_ID).asText());
-        } catch (IllegalArgumentException e) {
-            log.error("Pseudowire id is not an integer!");
-            return null;
-        }
-
-        return id;
-    }
-
-    @Override
-    public DefaultL2TunnelDescription decode(ObjectNode json, CodecContext context) {
-
-        Integer id = parsePwId(json.path(PW_ID).asText());
-
-        ConnectPoint cP1, cP2;
-        cP1 = ConnectPoint.deviceConnectPoint(json.path(CP1).asText());
-        cP2 = ConnectPoint.deviceConnectPoint(json.path(CP2).asText());
-
-        VlanId cP1InnerVlan, cP1OuterVlan, cP2InnerVlan, cP2OuterVlan, sdTag;
-        cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText());
-        cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText());
-        cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText());
-        cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText());
-        sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText());
-
-        L2Mode mode = parseMode(json.path(MODE).asText());
-        MplsLabel pwLabel = parsePWLabel(json.path(PW_LABEL).asText());
-
-        DefaultL2Tunnel l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel);
-        DefaultL2TunnelPolicy l2Policy = new DefaultL2TunnelPolicy(id, cP1, cP1InnerVlan, cP1OuterVlan,
-                                             cP2, cP2InnerVlan, cP2OuterVlan);
-        return new DefaultL2TunnelDescription(l2Tunnel, l2Policy);
-
-    }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
deleted file mode 100644
index 4867c90..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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.web;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.util.ItemNotFoundException;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.onlab.util.Tools.nullIsIllegal;
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove pseudowires.
- */
-@Path("pseudowire")
-public class PseudowireWebResource extends AbstractWebResource {
-
-    private static final PseudowireCodec PSEUDOWIRE_CODEC = new PseudowireCodec();
-    public static final String PWS = "pseudowires";
-    private static final String PWS_KEY_ERROR = "Pseudowires key must be present.";
-
-    private static Logger log = LoggerFactory
-            .getLogger(PseudowireWebResource.class);
-
-    /**
-     * Get all pseudowires.
-     * Returns an array of pseudowires.
-     *
-     * @return status of OK
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getPseudowire() {
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-
-        log.debug("Fetching pseudowires form rest api!");
-
-        List<L2TunnelPolicy> policies = srService.getL2Policies();
-        List<L2Tunnel> tunnels = srService.getL2Tunnels();
-        List<DefaultL2TunnelDescription> pseudowires = tunnels.stream()
-                .map(l2Tunnel -> {
-                    L2TunnelPolicy policy = null;
-                    for (L2TunnelPolicy l2Policy : policies) {
-                        if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
-                            policy = l2Policy;
-                            break;
-                        }
-                    }
-
-                    // return a copy
-                    return new DefaultL2TunnelDescription(l2Tunnel, policy);
-                })
-                .collect(Collectors.toList());
-
-        ObjectNode result = new ObjectMapper().createObjectNode();
-        result.set("pseudowires", new PseudowireCodec().encode(pseudowires, this));
-
-        return ok(result.toString()).build();
-    }
-
-    /**
-     * Create a new pseudowire.
-     *
-     * @param input JSON stream for pseudowire to create
-     * @return Response with appropriate status
-     * @throws IOException Throws IO exception.
-     * @onos.rsModel PseudowireCreate
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createPseudowire(InputStream input) throws IOException {
-
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        List<Pair<DefaultL2TunnelDescription, String>> failed = new ArrayList<>();
-        List<Pair<JsonNode, String>> undecoded = new ArrayList<>();
-
-        DefaultL2TunnelDescription pseudowire;
-        try {
-            pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
-
-            // pseudowire decoded, try to instantiate it, if we fail add it to failed list
-            long tunId = pseudowire.l2Tunnel().tunnelId();
-            log.debug("Creating pseudowire {} from rest api!", tunId);
-
-            L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
-            if (res != L2TunnelHandler.Result.SUCCESS) {
-                log.error("Could not create pseudowire {} : {}", pseudowire.l2Tunnel().tunnelId(),
-                          res.getSpecificError());
-                failed.add(Pair.of(pseudowire, res.getSpecificError()));
-            }
-        } catch (IllegalArgumentException e) {
-            log.debug("Pseudowire could not be decoded : {}", e.getMessage());
-            undecoded.add(Pair.of(pseudowireJson, e.getMessage()));
-        }
-
-        if ((failed.size() == 0) && (undecoded.size() == 0)) {
-            // pseudowire instantiated correctly
-            return Response.ok().build();
-        } else {
-            // failed to decode or instantiate pseudowire, return the reason
-            PseudowireCodec pwCodec = new PseudowireCodec();
-            ObjectNode result = pwCodec.encodeFailedPseudowires(failed, undecoded, this);
-            return Response.serverError().entity(result).build();
-        }
-    }
-
-    /**
-     * Create a bulk of pseudowires.
-     *
-     * @param input JSON stream for pseudowires to create
-     * @return Response with appropriate status
-     * @throws IOException Throws IO exception.
-     * @onos.rsModel PseudowireCreateBulk
-     */
-    @POST
-    @Path("/bulk")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createPseudowiresBulk(InputStream input) throws IOException {
-
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Pair<List<Pair<JsonNode, String>>, List<L2TunnelDescription>> pseudowires;
-
-        try {
-            ArrayNode pseudowiresArray = nullIsIllegal((ArrayNode) pseudowireJson.get(PWS), PWS_KEY_ERROR);
-            // get two lists, first one contains pseudowires that we were unable to decode
-            // that have faulty arguments, second one contains pseudowires that we decoded
-            // succesfully
-            pseudowires = PSEUDOWIRE_CODEC.decodePws(pseudowiresArray, this);
-        } catch (ItemNotFoundException e) {
-            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
-        }
-
-        log.debug("Creating pseudowires {} from rest api!", pseudowires);
-        List<Pair<DefaultL2TunnelDescription, String>> failed = new ArrayList<>();
-        for (L2TunnelDescription pw : pseudowires.getRight()) {
-            L2TunnelHandler.Result res = srService.addPseudowire(pw);
-            if (res != L2TunnelHandler.Result.SUCCESS) {
-                log.error("Could not create pseudowire {} : {}", pw.l2Tunnel().tunnelId(), res.getSpecificError());
-                failed.add(Pair.of((DefaultL2TunnelDescription) pw, res.getSpecificError()));
-            }
-        }
-        List<Pair<JsonNode, String>> undecodedPws = pseudowires.getLeft();
-
-        if ((failed.size() == 0) && (undecodedPws.size() == 0)) {
-            // all pseudowires were decoded and instantiated succesfully
-            return Response.ok().build();
-        } else {
-            PseudowireCodec pwCodec = new PseudowireCodec();
-            // some failed, need to report them to user
-            ObjectNode result = pwCodec.encodeFailedPseudowires(failed, undecodedPws, this);
-            return Response.serverError().entity(result).build();
-        }
-    }
-
-    /**
-     * Delete a pseudowire.
-     *
-     * @param input JSON stream for pseudowire to delete
-     * @return Response with appropriate status
-     * @throws IOException Throws IO exception.
-     * @onos.rsModel PseudowireDelete
-     */
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response removePseudowire(InputStream input) throws IOException {
-
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-
-        Integer pseudowireId = PSEUDOWIRE_CODEC.decodeId(pseudowireJson);
-        if (pseudowireId == null) {
-            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
-        }
-
-        log.debug("Deleting pseudowire {} from rest api!", pseudowireId);
-
-        L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
-        switch (res) {
-            case WRONG_PARAMETERS:
-            case INTERNAL_ERROR:
-                log.error("Pseudowire {} could not be removed : {}",
-                          pseudowireId, res.getSpecificError());
-                return Response.noContent().build();
-            case SUCCESS:
-                log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
-                return Response.noContent().build();
-            default:
-                return Response.noContent().build();
-        }
-    }
-
-    /**
-     * Delete a bulk of pseudowires.
-     *
-     * @param input JSON stream for pseudowires to delete
-     * @return Response with appropriate status
-     * @throws IOException Throws IO exception.
-     * @onos.rsModel PseudowireDeleteBulk
-     */
-    @DELETE
-    @Path("/bulk")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response removePseudowiresBulk(InputStream input) throws IOException {
-
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-
-        List<Integer> ids = new ArrayList<>();
-
-        // try to parse all ids, if key is not present, or if an id is not an int
-        // throw an exception and stop process
-        try {
-            for (JsonNode node : pseudowireJson.withArray(PWS)) {
-                Integer idToDelete = PseudowireCodec.decodeId((ObjectNode) node);
-                if (idToDelete == null) {
-                    log.error("Error when parsing pseudowire for deletion in REST API.");
-                    throw new IllegalArgumentException("Id of pseudowire should be an integer!");
-                }
-                ids.add(idToDelete);
-            }
-        } catch (IllegalArgumentException e) {
-            log.error("Pseudowire ID should be an integer.");
-            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
-        } catch (UnsupportedOperationException e) {
-            log.error("Pseudowires for deletion should be an array of pseudowire ids.");
-            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
-        }
-
-        for (Integer pseudowireId : ids) {
-            L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
-            switch (res) {
-                case WRONG_PARAMETERS:
-                case INTERNAL_ERROR:
-                    log.error("Pseudowire {} could not be removed, internal error : {}",
-                              pseudowireId, res.getSpecificError());
-                    break;
-                case SUCCESS:
-                    log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
-                    break;
-                default:
-            }
-        }
-
-        return Response.noContent().build();
-    }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
deleted file mode 100644
index 6704030..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.web;
-
-import org.onlab.rest.AbstractWebApplication;
-
-import java.util.Set;
-
-/**
- * Segment Routing REST API.
- */
-public class SegmentRoutingWebApplication extends AbstractWebApplication {
-    @Override
-    public Set<Class<?>> getClasses() {
-        return getClasses(
-                PseudowireWebResource.class,
-                McastWebResource.class,
-                XconnectWebResource.class
-        );
-    }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java
deleted file mode 100644
index b2d74b1..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.web;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.segmentrouting.DefaultTunnel;
-import org.onosproject.segmentrouting.Tunnel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Codec of Tunnel class.
- */
-public final class TunnelCodec extends JsonCodec<Tunnel> {
-
-    // JSON field names
-    private static final String TUNNEL_ID = "tunnel_id";
-    private static final String GROUP_ID = "group_id";
-    private static final String LABEL_PATH = "label_path";
-
-    @Override
-    public ObjectNode encode(Tunnel tunnel, CodecContext context) {
-        final ObjectNode result = context.mapper().createObjectNode()
-                .put(TUNNEL_ID, tunnel.id());
-
-        result.put(GROUP_ID, tunnel.groupId());
-
-        final ArrayNode jsonLabelIds = result.putArray(LABEL_PATH);
-
-        tunnel.labelIds().forEach(label -> jsonLabelIds.add(label.intValue()));
-
-        return result;
-    }
-
-    @Override
-    public DefaultTunnel decode(ObjectNode json, CodecContext context) {
-
-        String tid = json.path(TUNNEL_ID).asText();
-        List<Integer> labels = new ArrayList<>();
-
-        if (!json.path(LABEL_PATH).isMissingNode()) {
-            ArrayNode labelArray = (ArrayNode) json.path(LABEL_PATH);
-            for (JsonNode o : labelArray) {
-                labels.add(o.asInt());
-            }
-        }
-
-        return new DefaultTunnel(tid, labels);
-    }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
deleted file mode 100644
index 010f6c9..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove segment routing tunnels.
- */
-// @Path("tunnel")
-public class TunnelWebResource extends AbstractWebResource {
-
-    private static final TunnelCodec TUNNEL_CODEC = new TunnelCodec();
-
-    /**
-     * Get all segment routing tunnels.
-     * Returns an array of segment routing tunnels.
-     *
-     * @return status of OK
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getTunnel() {
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        List<Tunnel> tunnels = srService.getTunnels();
-        ObjectNode result = new ObjectMapper().createObjectNode();
-        result.set("tunnel", new TunnelCodec().encode(tunnels, this));
-
-        return ok(result.toString()).build();
-    }
-
-    /**
-     * Create a new segment routing tunnel.
-     *
-     * @param input JSON stream for tunnel to create
-     * @return status of the request - OK if the tunnel is created,
-     * @throws IOException if the JSON is invalid
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response createTunnel(InputStream input) throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode tunnelJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this);
-        srService.createTunnel(tunnelInfo);
-
-        return Response.ok().build();
-    }
-
-    /**
-     * Delete a segment routing tunnel.
-     *
-     * @param input JSON stream for tunnel to delete
-     * @return 204 NO CONTENT, if the tunnel is removed
-     * @throws IOException if JSON is invalid
-     */
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response removeTunnel(InputStream input) throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode tunnelJson = readTreeFromStream(mapper, input);
-        SegmentRoutingService srService = get(SegmentRoutingService.class);
-        Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this);
-        srService.removeTunnel(tunnelInfo);
-
-        return Response.noContent().build();
-    }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/XconnectWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/XconnectWebResource.java
deleted file mode 100644
index 51c9cc9..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/XconnectWebResource.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2018-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.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.xconnect.api.XconnectDesc;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Set;
-
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove Xconnects.
- */
-@Path("xconnect")
-public class XconnectWebResource extends AbstractWebResource {
-    private static final String XCONNECTS = "xconnects";
-    private static Logger log = LoggerFactory.getLogger(XconnectWebResource.class);
-
-    /**
-     * Gets all Xconnects.
-     *
-     * @return an array of xconnects
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getXconnects() {
-        XconnectService xconnectService = get(XconnectService.class);
-        Set<XconnectDesc> xconnects = xconnectService.getXconnects();
-
-        ObjectNode result = encodeArray(XconnectDesc.class, XCONNECTS, xconnects);
-        return ok(result).build();
-    }
-
-    /**
-     * Create a new Xconnect.
-     *
-     * @param input JSON stream for xconnect to create
-     * @return 200 OK
-     * @throws IOException Throws IO exception
-     * @onos.rsModel XconnectCreate
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response addOrUpdateXconnect(InputStream input) throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode json = readTreeFromStream(mapper, input);
-        XconnectDesc desc = codec(XconnectDesc.class).decode(json, this);
-
-        if (desc.endpoints().size() != 2) {
-            throw new IllegalArgumentException("Ports should have only two items.");
-        }
-
-        XconnectService xconnectService = get(XconnectService.class);
-        xconnectService.addOrUpdateXconnect(desc.key().deviceId(), desc.key().vlanId(), desc.endpoints());
-
-        return Response.ok().build();
-    }
-
-
-    /**
-     * Delete an existing Xconnect.
-     *
-     * @param input JSON stream for xconnect to remove
-     * @return 204 NO CONTENT
-     * @throws IOException Throws IO exception
-     * @onos.rsModel XconnectDelete
-     */
-    @DELETE
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response removeXconnect(InputStream input) throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode json = readTreeFromStream(mapper, input);
-        XconnectDesc desc = codec(XconnectDesc.class).decode(json, this);
-
-        XconnectService xconnectService = get(XconnectService.class);
-        xconnectService.removeXonnect(desc.key().deviceId(), desc.key().vlanId());
-
-        return Response.noContent().build();
-    }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java
deleted file mode 100644
index ff9555e..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Segment routing application components.
- */
-package org.onosproject.segmentrouting.web;
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreate.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreate.json
deleted file mode 100644
index 315d01d..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreate.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "type": "object",
-  "title": "pseudowire-creation",
-  "required": [
-    "pwId",
-    "cP1",
-    "cP2",
-    "cP1InnerTag",
-    "cP1OuterTag",
-    "cP2InnerTag",
-    "cP2OuterTag",
-    "mode",
-    "sdTag",
-    "pwLabel"
-  ],
-  "properties": {
-    "pwId": {
-      "type": "string",
-      "example": "42",
-      "description": "Id of pseudowire to create."
-    },
-    "cP1": {
-      "type": "string",
-      "example": "of:0000000000000227/25",
-      "description": "Pseudowire connection point 1."
-    },
-    "cP2": {
-      "type": "string",
-      "example": "of:0000000000000226/25",
-      "description": "Pseudowire connection point 2."
-    },
-    "cP1InnerTag": {
-      "type": "string",
-      "example": "101",
-      "description": "Inner vlan for pseudowire connection point 1."
-    },
-    "cP1OuterTag": {
-      "type": "string",
-      "example": "",
-      "description": "Outer vlan for pseudowire connection point 1."
-    },
-    "cP2InnerTag": {
-      "type": "string",
-      "example": "101",
-      "description": "Inner vlan for pseudowire connection point 2."
-    },
-    "cP2OuterTag": {
-      "type": "string",
-      "example": "",
-      "description": "Outer vlan for pseudowire connection point 2."
-    },
-    "mode": {
-      "type": "string",
-      "example": "RAW",
-      "description": "Working mode of pseudowire."
-    },
-    "sDTag": {
-      "type": "string",
-      "example": "",
-      "description": "Service delimiting tag of the pseudowire"
-    },
-    "pwLabel": {
-      "type": "256",
-      "example": "1577",
-      "description": "Pseudowire label."
-    }
-  }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreateBulk.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreateBulk.json
deleted file mode 100644
index 752e6eb..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreateBulk.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
-  "type": "object",
-  "title": "pseudowire-creation-bulk",
-  "required": [
-    "pseudowires"
-  ],
-  "properties": {
-    "pseudowires": {
-      "type": "array",
-      "items": {
-        "properties": {
-          "pwId": {
-            "type": "string",
-            "example": "42",
-            "description": "Id of pseudowire to create."
-          },
-          "cP1": {
-            "type": "string",
-            "example": "of:0000000000000227/25",
-            "description": "Pseudowire connection point 1."
-          },
-          "cP2": {
-            "type": "string",
-            "example": "of:0000000000000226/25",
-            "description": "Pseudowire connection point 2."
-          },
-          "cP1InnerTag": {
-            "type": "string",
-            "example": "101",
-            "description": "Inner vlan for pseudowire connection point 1."
-          },
-          "cP1OuterTag": {
-            "type": "string",
-            "example": "",
-            "description": "Outer vlan for pseudowire connection point 1."
-          },
-          "cP2InnerTag": {
-            "type": "string",
-            "example": "101",
-            "description": "Inner vlan for pseudowire connection point 2."
-          },
-          "cP2OuterTag": {
-            "type": "string",
-            "example": "",
-            "description": "Outer vlan for pseudowire connection point 2."
-          },
-          "mode": {
-            "type": "string",
-            "example": "RAW",
-            "description": "Working mode of pseudowire."
-          },
-          "sDTag": {
-            "type": "string",
-            "example": "",
-            "description": "Service delimiting tag of the pseudowire"
-          },
-          "pwLabel": {
-            "type": "256",
-            "example": "1577",
-            "description": "Pseudowire label."
-          }
-        }
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDelete.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDelete.json
deleted file mode 100644
index 4dd5c04..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDelete.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "type": "object",
-  "title": "pseudowire-deletion",
-  "required": [
-    "pwId"
-  ],
-  "properties": {
-    "pwId": {
-      "type": "string",
-      "example": "42",
-      "description": "Id of pseudowire to delete."
-    }
-  }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDeleteBulk.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDeleteBulk.json
deleted file mode 100644
index 2edc7e6..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDeleteBulk.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "type": "object",
-  "title": "pseudowire-deletion-bulk",
-  "required": [
-    "pseudowires"
-  ],
-  "properties": {
-    "pseudowires": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "title": "pseudowire-1",
-        "required": [
-          "pwId"
-        ],
-        "properties": {
-          "pwId": {
-            "type": "string",
-            "example": "42",
-            "description": "Id of pseudowire to Delete."
-          }
-        }
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/XconnectCreate.json b/apps/segmentrouting/web/src/main/resources/definitions/XconnectCreate.json
deleted file mode 100644
index 87a776c..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/XconnectCreate.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
-  "type": "object",
-  "title": "xconnect-creation",
-  "required": [
-    "deviceId",
-    "vlanId",
-    "endpoints"
-  ],
-  "properties": {
-    "deviceId": {
-      "type": "string",
-      "example": "of:0000000000000201",
-      "description": "Device ID"
-    },
-    "vlanId": {
-      "type": "string",
-      "example": "94",
-      "description": "VLAN ID"
-    },
-    "endpoints": {
-      "type": "array",
-      "items": {
-        "type": "int8",
-        "description": "Port number"
-      },
-      "example": [1, 2]
-    }
-  }
-}
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/XconnectDelete.json b/apps/segmentrouting/web/src/main/resources/definitions/XconnectDelete.json
deleted file mode 100644
index fcd5f66..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/XconnectDelete.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "type": "object",
-  "title": "xconnect-deletion",
-  "required": [
-    "deviceId",
-    "vlanId"
-  ],
-  "properties": {
-    "deviceId": {
-      "type": "string",
-      "example": "of:0000000000000201",
-      "description": "Device ID"
-    },
-    "vlanId": {
-      "type": "string",
-      "example": "94",
-      "description": "VLAN ID"
-    }
-  }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml b/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 1362728..0000000
--- a/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://java.sun.com/xml/ns/javaee"
-         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-         id="ONOS" version="2.5">
-    <display-name>Segment Routing Server REST API v1.0</display-name>
-
-    <security-constraint>
-        <web-resource-collection>
-            <web-resource-name>Secured</web-resource-name>
-            <url-pattern>/*</url-pattern>
-        </web-resource-collection>
-        <auth-constraint>
-            <role-name>admin</role-name>
-            <role-name>viewer</role-name>
-        </auth-constraint>
-    </security-constraint>
-
-    <security-role>
-        <role-name>admin</role-name>
-        <role-name>viewer</role-name>
-    </security-role>
-
-    <login-config>
-        <auth-method>BASIC</auth-method>
-        <realm-name>karaf</realm-name>
-    </login-config>
-
-    <servlet>
-        <servlet-name>JAX-RS Service</servlet-name>
-        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
-        <init-param>
-            <param-name>javax.ws.rs.Application</param-name>
-            <param-value>org.onosproject.segmentrouting.web.SegmentRoutingWebApplication</param-value>
-        </init-param>
-        <load-on-startup>1</load-on-startup>
-    </servlet>
-
-    <servlet-mapping>
-        <servlet-name>JAX-RS Service</servlet-name>
-        <url-pattern>/*</url-pattern>
-    </servlet-mapping>
-</web-app>
diff --git a/apps/t3/BUILD b/apps/t3/BUILD
deleted file mode 100644
index 0e444bf..0000000
--- a/apps/t3/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-BUNDLES = [
-    "//apps/t3/web:onos-apps-t3-web",
-    "//apps/t3/app:onos-apps-t3-app",
-]
-
-onos_app(
-    app_name = "org.onosproject.t3",
-    category = "Utilities",
-    description = "Provides static analysis of flows and groups " +
-                  "to determine the possible paths a packet may take.",
-    included_bundles = BUNDLES,
-    required_apps = [
-        "org.onosproject.segmentrouting",
-        "org.onosproject.route-service",
-        "org.onosproject.mcast",
-    ],
-    title = "Trellis Troubleshooting Toolkit",
-    url = "https://wiki.opencord.org/pages/viewpage.action?pageId=4456974",
-)
diff --git a/apps/t3/app/BUILD b/apps/t3/app/BUILD
deleted file mode 100644
index 81173f6..0000000
--- a/apps/t3/app/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + KRYO + JACKSON + CLI + [
-    "//core/store/serializers:onos-core-serializers",
-    "//core/store/primitives:onos-core-primitives",
-    "//drivers/default:onos-drivers-default",
-    "//apps/segmentrouting/app:onos-apps-segmentrouting-app",
-    "//apps/route-service/api:onos-apps-route-service-api",
-    "//apps/mcast/api:onos-apps-mcast-api",
-]
-
-TEST_DEPS = TEST_ADAPTERS + [
-    "//utils/misc:onlab-misc",
-    "//apps/route-service/api:onos-apps-route-service-api-tests",
-]
-
-osgi_jar_with_tests(
-    karaf_command_packages = ["org.onosproject.t3.cli"],
-    test_deps = TEST_DEPS,
-    deps = COMPILE_DEPS,
-)
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/AbstractNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/AbstractNib.java
deleted file mode 100644
index 652c974..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/AbstractNib.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-/**
- * Base abstraction of Network Information Base (NIB).
- */
-public abstract class AbstractNib {
-
-    protected NibProfile nibProfile;
-
-    /**
-     * Sets a profile describing this NIB.
-     *
-     * @param nibProfile NIB profile
-     */
-    public void setProfile(NibProfile nibProfile) {
-        this.nibProfile = nibProfile;
-    }
-
-    /**
-     * Returns the current profile of this NIB.
-     *
-     * @return NIB profile
-     */
-    public NibProfile getProfile() {
-        return nibProfile;
-    }
-
-    /**
-     * Checks this NIB is valid.
-     *
-     * @return true (valid) only if this NIB is already filled with any source. false means invalid
-     */
-    public boolean isValid() {
-        if (nibProfile != null) {
-            return nibProfile.isValid();
-        } else {
-            return false;
-        }
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/DeviceNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/DeviceNib.java
deleted file mode 100644
index aca8418..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/DeviceNib.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Represents Network Information Base (NIB) for devices
- * and supports alternative functions to
- * {@link org.onosproject.net.device.DeviceService} for offline data.
- */
-public class DeviceNib extends AbstractNib {
-
-    private Map<Device, Set<Port>> devicePortMap;
-
-    // use the singleton helper to create the instance
-    protected DeviceNib() {
-    }
-
-    /**
-     * Sets a map of device : ports of the device.
-     *
-     * @param devicePortMap device-ports map
-     */
-    public void setDevicePortMap(Map<Device, Set<Port>> devicePortMap) {
-        this.devicePortMap = devicePortMap;
-    }
-
-    /**
-     * Returns the device-ports map.
-     *
-     * @return device-ports map
-     */
-    public Map<Device, Set<Port>> getDevicePortMap() {
-        return ImmutableMap.copyOf(devicePortMap);
-    }
-
-    /**
-     * Returns the device with the specified identifier.
-     *
-     * @param deviceId device identifier
-     * @return device or null if one with the given identifier is not known
-     */
-    public Device getDevice(DeviceId deviceId) {
-        return devicePortMap.keySet().stream()
-                .filter(device -> device.id().equals(deviceId))
-                .findFirst().orElse(null);
-    }
-
-    /**
-     * Returns the port with the specified connect point.
-     *
-     * @param cp connect point
-     * @return device port
-     */
-    public Port getPort(ConnectPoint cp) {
-        return devicePortMap.get(getDevice(cp.deviceId())).stream()
-                .filter(port -> port.number().equals(cp.port()))
-                .findFirst().orElse(null);
-    }
-
-    /**
-     * Returns the list of ports associated with the device.
-     *
-     * @param deviceId device identifier
-     * @return list of ports
-     */
-    public List<Port> getPorts(DeviceId deviceId) {
-        return ImmutableList.copyOf(devicePortMap.get(getDevice(deviceId)));
-    }
-
-    /**
-     * Indicates whether or not the device is presently online and available.
-     * Availability, unlike reachability, denotes whether ANY node in the
-     * cluster can discover that this device is in an operational state,
-     * this does not necessarily mean that there exists a node that can
-     * control this device.
-     *
-     * @param deviceId device identifier
-     * @return true if the device is available
-     */
-    public boolean isAvailable(DeviceId deviceId) {
-        Device device = getDevice(deviceId);
-        // TODO: may need an extra REST API to get availableDevices from DeviceService, not from device annotations
-        return device.annotations().value("available").equals("true") ? true : false;
-    }
-
-    /**
-     * Returns the singleton instance of devices NIB.
-     *
-     * @return instance of devices NIB
-     */
-    public static DeviceNib getInstance() {
-        return DeviceNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final DeviceNib INSTANCE = new DeviceNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/DriverNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/DriverNib.java
deleted file mode 100644
index edee901..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/DriverNib.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-
-/**
- * Represents Network Information Base (NIB) for drivers
- * and supports alternative functions to
- * {@link org.onosproject.net.driver.DriverService} for offline data.
- */
-public class DriverNib extends AbstractNib {
-
-    private Map<DeviceId, String> deviceDriverMap;
-
-    // use the singleton helper to create the instance
-    protected DriverNib() {
-    }
-
-    /**
-     * Sets a map of device id : driver name.
-     *
-     * @param deviceDriverMap device-driver map
-     */
-    public void setDeviceDriverMap(Map<DeviceId, String> deviceDriverMap) {
-        this.deviceDriverMap = deviceDriverMap;
-    }
-
-    /**
-     * Returns the device-driver map.
-     *
-     * @return device-driver map
-     */
-    public Map<DeviceId, String> getDeviceDriverMap() {
-        return ImmutableMap.copyOf(deviceDriverMap);
-    }
-
-    /**
-     * Returns a driver name of the given device.
-     *
-     * @param deviceId the device id
-     * @return the driver name
-     */
-    public String getDriverName(DeviceId deviceId) {
-        return deviceDriverMap.get(deviceId);
-    }
-
-    /**
-     * Returns the singleton instance of drivers NIB.
-     *
-     * @return instance of drivers NIB
-     */
-    public static DriverNib getInstance() {
-        return DriverNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final DriverNib INSTANCE = new DriverNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/EdgePortNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/EdgePortNib.java
deleted file mode 100644
index 060f9c4..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/EdgePortNib.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Represents Network Information Base (NIB) for edge ports
- * and supports alternative functions to
- * {@link org.onosproject.net.edge.EdgePortService} for offline data.
- */
-public class EdgePortNib extends AbstractNib {
-
-    private Map<DeviceId, Set<ConnectPoint>> edgePorts;
-
-    // use the singleton helper to create the instance
-    protected EdgePortNib() {
-    }
-
-    /**
-     * Sets a map of device id : edge ports of the device.
-     *
-     * @param edgePorts device-edge ports map
-     */
-    public void setEdgePorts(Map<DeviceId, Set<ConnectPoint>> edgePorts) {
-        this.edgePorts = edgePorts;
-    }
-
-    /**
-     * Returns the device-edge ports map.
-     * @return device-edge ports map
-     */
-    public Map<DeviceId, Set<ConnectPoint>> getEdgePorts() {
-        return ImmutableMap.copyOf(edgePorts);
-    }
-
-    /**
-     * Indicates whether or not the specified connection point is an edge point.
-     *
-     * @param point connection point
-     * @return true if edge point
-     */
-    public boolean isEdgePoint(ConnectPoint point) {
-        Set<ConnectPoint> connectPoints = edgePorts.get(point.deviceId());
-        return connectPoints != null && connectPoints.contains(point);
-    }
-
-    /**
-     * Returns the singleton instance of edge ports NIB.
-     *
-     * @return instance of edge ports NIB
-     */
-    public static EdgePortNib getInstance() {
-        return EdgePortNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final EdgePortNib INSTANCE = new EdgePortNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/FlowNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/FlowNib.java
deleted file mode 100644
index b9f2226..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/FlowNib.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.flow.FlowEntry;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for flows
- * and supports alternative functions to
- * {@link org.onosproject.net.flow.FlowRuleService} for offline data.
- */
-public class FlowNib extends AbstractNib {
-
-    // TODO with method optimization, store into subdivided structures at the first load
-    private Set<FlowEntry> flows;
-
-    // use the singleton helper to create the instance
-    protected FlowNib() {
-    }
-
-    /**
-     * Sets a set of flows.
-     *
-     * @param flows flow set
-     */
-    public void setFlows(Set<FlowEntry> flows) {
-        this.flows = flows;
-    }
-
-    /**
-     * Returns the set of flows.
-     *
-     * @return flow set
-     */
-    public Set<FlowEntry> getFlows() {
-        return ImmutableSet.copyOf(flows);
-    }
-
-    /**
-     * Returns a list of rules filtered by device id and flow state.
-     *
-     * @param deviceId the device id to lookup
-     * @param flowState the flow state to lookup
-     * @return collection of flow entries
-     */
-    public Iterable<FlowEntry> getFlowEntriesByState(DeviceId deviceId, FlowEntry.FlowEntryState flowState) {
-        Set<FlowEntry> flowsFiltered = flows.stream()
-                .filter(flow -> flow.state() == flowState
-                        && flow.deviceId().equals(deviceId))
-                .collect(Collectors.toSet());
-        return flowsFiltered != null ? ImmutableSet.copyOf(flowsFiltered) : ImmutableSet.of();
-    }
-
-    /**
-     * Returns the singleton instance of flows NIB.
-     *
-     * @return instance of flows NIB
-     */
-    public static FlowNib getInstance() {
-        return SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final FlowNib INSTANCE = new FlowNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupNib.java
deleted file mode 100644
index b1fb563..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupNib.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.group.Group;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for groups
- * and supports alternative functions to
- * {@link org.onosproject.net.group.GroupService} for offline data.
- */
-public class GroupNib extends AbstractNib {
-
-    // TODO with method optimization, store into subdivided structures at the first load
-    private Set<Group> groups;
-
-    // use the singleton helper to create the instance
-    protected GroupNib() {
-    }
-
-    /**
-     * Sets a set of groups.
-     *
-     * @param groups group set
-     */
-    public void setGroups(Set<Group> groups) {
-        this.groups = groups;
-    }
-
-    /**
-     * Returns the set of groups.
-     *
-     * @return group set
-     */
-    public Set<Group> getGroups() {
-        return ImmutableSet.copyOf(groups);
-    }
-
-    /**
-     * Returns all groups associated with the given device.
-     *
-     * @param deviceId device ID to get groups for
-     * @return iterable of device's groups
-     */
-    public Iterable<Group> getGroups(DeviceId deviceId) {
-        Set<Group> groupsFiltered = groups.stream()
-                .filter(g -> g.deviceId().equals(deviceId))
-                .collect(Collectors.toSet());
-        return groupsFiltered != null ? ImmutableSet.copyOf(groupsFiltered) : ImmutableSet.of();
-    }
-
-    /**
-     * Returns the singleton instance of groups NIB.
-     *
-     * @return instance of groups NIB
-     */
-    public static GroupNib getInstance() {
-        return GroupNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final GroupNib INSTANCE = new GroupNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupsInDevice.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupsInDevice.java
deleted file mode 100644
index 74203af..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupsInDevice.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2017-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.t3.api;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.group.Group;
-
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Class to represent the groups in a device for a given output and packet.
- */
-//FIXME consider name change.
-public class GroupsInDevice {
-
-    private ConnectPoint output;
-    private List<Group> groups;
-    private TrafficSelector selector;
-
-    /**
-     * Saves the given groups for the output connect point and the selector.
-     *
-     * @param output   the output connect point
-     * @param groups   the groups
-     * @param selector the selector representing the final packet
-     */
-    public GroupsInDevice(ConnectPoint output, List<Group> groups, TrafficSelector selector) {
-
-        this.output = output;
-        this.groups = groups;
-        this.selector = selector;
-    }
-
-    /**
-     * Returns the output connect point.
-     *
-     * @return the connect point
-     */
-    public ConnectPoint getOutput() {
-        return output;
-    }
-
-    /**
-     * Returns the groups.
-     *
-     * @return groups.
-     */
-    public List<Group> getGroups() {
-        return groups;
-    }
-
-    /**
-     * Returns the final packet after traversing the network.
-     *
-     * @return the selector with packet info
-     */
-    public TrafficSelector getFinalPacket() {
-        return selector;
-    }
-
-    /**
-     * Updates the final packet.
-     *
-     * @param updatedPacket the updated final packet
-     */
-    public void setFinalPacket(TrafficSelector updatedPacket) {
-        selector = updatedPacket;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        GroupsInDevice that = (GroupsInDevice) o;
-
-        return Objects.equals(output, that.output) &&
-                Objects.equals(groups, that.groups) &&
-                Objects.equals(selector, that.selector);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(output, groups, selector);
-    }
-
-    @Override
-    public String toString() {
-        return "GroupsInDevice{" +
-
-                "output=" + output +
-                ", groups=" + groups +
-                ", selector=" + selector +
-                '}';
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/HostNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/HostNib.java
deleted file mode 100644
index 2ba68d1..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/HostNib.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for hosts
- * and supports alternative functions to
- * {@link org.onosproject.net.host.HostService} for offline data.
- */
-public class HostNib extends AbstractNib {
-
-    // TODO with method optimization, store into subdivided structures at the first load
-    private Set<Host> hosts;
-
-    // use the singleton helper to create the instance
-    protected HostNib() {
-    }
-
-    /**
-     * Sets a set of hosts.
-     *
-     * @param hosts host set
-     */
-    public void setHosts(Set<Host> hosts) {
-        this.hosts = hosts;
-    }
-
-    /**
-     * Returns the set of hosts.
-     *
-     * @return host set
-     */
-    public Set<Host> getHosts() {
-        return ImmutableSet.copyOf(hosts);
-    }
-
-    /**
-     * Returns the host with the specified identifier.
-     *
-     * @param hostId host identifier
-     * @return host or null if one with the given identifier is not known
-     */
-    public Host getHost(HostId hostId) {
-        return hosts.stream()
-                .filter(host -> host.id().equals(hostId))
-                .findFirst().orElse(null);
-    }
-
-    /**
-     * Returns the set of hosts whose most recent location is the specified
-     * connection point.
-     *
-     * @param connectPoint connection point
-     * @return set of hosts connected to the connection point
-     */
-    public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
-        // TODO extend this method to support matching on auxLocations as well
-        Set<Host> connectedHosts = hosts.stream()
-                .filter(host -> host.locations().contains(connectPoint))
-                .collect(Collectors.toSet());
-        return connectedHosts != null ? ImmutableSet.copyOf(connectedHosts) : ImmutableSet.of();
-    }
-
-    /**
-     * Returns the set of hosts that have the specified IP address.
-     *
-     * @param ip ip address
-     * @return set of hosts with the given IP
-     */
-    public Set<Host> getHostsByIp(IpAddress ip) {
-        Set<Host> hostsByIp = hosts.stream()
-                .filter(host -> host.ipAddresses().contains(ip))
-                .collect(Collectors.toSet());
-        return hostsByIp != null ? ImmutableSet.copyOf(hostsByIp) : ImmutableSet.of();
-    }
-
-    /**
-     * Returns the set of hosts that have the specified MAC address.
-     *
-     * @param mac mac address
-     * @return set of hosts with the given mac
-     */
-    public Set<Host> getHostsByMac(MacAddress mac) {
-        Set<Host> hostsByMac = hosts.stream()
-                .filter(host -> host.mac().equals(mac))
-                .collect(Collectors.toSet());
-        return hostsByMac != null ? ImmutableSet.copyOf(hostsByMac) : ImmutableSet.of();
-    }
-
-    /**
-     * Returns the singleton instance of hosts NIB.
-     *
-     * @return instance of hosts NIB
-     */
-    public static HostNib getInstance() {
-        return HostNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final HostNib INSTANCE = new HostNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/LinkNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/LinkNib.java
deleted file mode 100644
index 622a187..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/LinkNib.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Link;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for links
- * and supports alternative functions to
- * {@link org.onosproject.net.link.LinkService} for offline data.
- */
-public class LinkNib extends AbstractNib {
-
-    // TODO with method optimization, store into subdivided structures at the first load
-    private Set<Link> links;
-
-    // use the singleton helper to create the instance
-    protected LinkNib() {
-    }
-
-    /**
-     * Sets a set of links.
-     *
-     * @param links link set
-     */
-    public void setLinks(Set<Link> links) {
-        this.links = links;
-    }
-
-    /**
-     * Returns the set of links.
-     *
-     * @return link set
-     */
-    public Set<Link> getLinks() {
-        return ImmutableSet.copyOf(links);
-    }
-
-    /**
-     * Returns set of all infrastructure links leading from the specified
-     * connection point.
-     *
-     * @param connectPoint connection point
-     * @return set of device egress links
-     */
-    public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
-        Set<Link> egressLinks = links.stream()
-                .filter(link -> connectPoint.equals(link.src()))
-                .collect(Collectors.toSet());
-        return egressLinks != null ? ImmutableSet.copyOf(egressLinks) : ImmutableSet.of();
-    }
-
-    /**
-     * Returns the singleton instance of links NIB.
-     *
-     * @return instance of links NIB
-     */
-    public static LinkNib getInstance() {
-        return LinkNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final LinkNib INSTANCE = new LinkNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/MastershipNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/MastershipNib.java
deleted file mode 100644
index 733c590..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/MastershipNib.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-
-/**
- * Represents Network Information Base (NIB) for mastership
- * and supports alternative functions to
- * {@link org.onosproject.mastership.MastershipService} for offline data.
- */
-public class MastershipNib extends AbstractNib {
-
-    private Map<DeviceId, NodeId> deviceMasterMap;
-
-    // use the singleton helper to create the instance
-    protected MastershipNib() {
-    }
-
-    /**
-     * Sets a map of device id : master node id.
-     *
-     * @param deviceMasterMap device-master map
-     */
-    public void setDeviceMasterMap(Map<DeviceId, NodeId> deviceMasterMap) {
-        this.deviceMasterMap = deviceMasterMap;
-    }
-
-    /**
-     * Returns the device-master map.
-     *
-     * @return device-master map
-     */
-    public Map<DeviceId, NodeId> getDeviceMasterMap() {
-        return ImmutableMap.copyOf(deviceMasterMap);
-    }
-
-    /**
-     * Returns the current master for a given device.
-     *
-     * @param deviceId the identifier of the device
-     * @return the ID of the master controller for the device
-     */
-    public NodeId getMasterFor(DeviceId deviceId) {
-        return deviceMasterMap.get(deviceId);
-    }
-
-    /**
-     * Returns the singleton instance of mastership NIB.
-     *
-     * @return instance of mastership NIB
-     */
-    public static MastershipNib getInstance() {
-        return MastershipNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final MastershipNib INSTANCE = new MastershipNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/MulticastRouteNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/MulticastRouteNib.java
deleted file mode 100644
index 0bcdc1f..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/MulticastRouteNib.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Represents Network Information Base (NIB) for multicast routes
- * and supports alternative functions to
- * {@link org.onosproject.mcast.api.MulticastRouteService} for offline data.
- */
-public class MulticastRouteNib extends AbstractNib {
-
-    private Map<McastRoute, McastRouteData> mcastRoutes;
-
-    // use the singleton helper to create the instance
-    protected MulticastRouteNib() {
-    }
-
-    public void setMcastRoutes(Map<McastRoute, McastRouteData> mcastRoutes) {
-        this.mcastRoutes = mcastRoutes;
-    }
-
-    public Map<McastRoute, McastRouteData> getMcastRoutes() {
-        return ImmutableMap.copyOf(mcastRoutes);
-    }
-
-    /**
-     * Gets all Multicast routes in the system.
-     *
-     * @return set of Multicast routes
-     */
-    public Set<McastRoute> getRoutes() {
-        return ImmutableSet.copyOf(mcastRoutes.keySet());
-    }
-
-    /**
-     * Return the Multicast data for this route.
-     *
-     * @param route route
-     * @return the mcast route data
-     */
-    public McastRouteData routeData(McastRoute route) {
-        return mcastRoutes.get(route);
-    }
-
-    /**
-     * Returns the singleton instance of multicast routes NIB.
-     *
-     * @return instance of multicast routes NIB
-     */
-    public static MulticastRouteNib getInstance() {
-        return MulticastRouteNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final MulticastRouteNib INSTANCE = new MulticastRouteNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/NetworkConfigNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/NetworkConfigNib.java
deleted file mode 100644
index f3de961..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/NetworkConfigNib.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.slf4j.Logger;
-
-import java.util.Map;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Represents Network Information Base (NIB) for network configurations
- * and supports alternative functions to
- * {@link org.onosproject.net.config.NetworkConfigService} for offline data.
- */
-public class NetworkConfigNib extends AbstractNib {
-
-    private static final Logger log = getLogger(NetworkConfigNib.class);
-
-    // Map of str ConnectPoint : InterfaceConfig
-    private Map<String, Config> portConfigMap;
-    // Map of str DeviceId : SegmentRoutingDeviceConfig
-    private Map<String, Config> deviceConfigMap;
-
-    // use the singleton helper to create the instance
-    protected NetworkConfigNib() {
-    }
-
-    /**
-     * Sets a map of port : configuration to the port.
-     *
-     * @param portConfigMap port-config map
-     */
-    public void setPortConfigMap(Map<String, Config> portConfigMap) {
-         this.portConfigMap = portConfigMap;
-    }
-
-    /**
-     * Sets a map of device : configuration to the device.
-     *
-     * @param deviceConfigMap device-config map
-     */
-    public void setDeviceConfigMap(Map<String, Config> deviceConfigMap) {
-        this.deviceConfigMap = deviceConfigMap;
-    }
-
-    /**
-     * Returns the port-config map.
-     *
-     * @return port-config map
-     */
-    public Map<Object, Object> getPortConfigMap() {
-        return ImmutableMap.copyOf(portConfigMap);
-    }
-
-    /**
-     * Returns the device-config map.
-     *
-     * @return device-config map
-     */
-    public Map<Object, Object> getDeviceConfigMap() {
-        return ImmutableMap.copyOf(deviceConfigMap);
-    }
-
-    /**
-     * Returns the configuration for the specified subject and configuration
-     * class if one is available; null otherwise.
-     *
-     * @param subject     configuration subject
-     * @param configClass configuration class
-     * @param <S>         type of subject
-     * @param <C>         type of configuration
-     * @return configuration or null if one is not available
-     */
-    public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
-        if (configClass.equals(InterfaceConfig.class)) {
-            return (C) portConfigMap.get(subject.toString());
-        } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
-            return (C) deviceConfigMap.get(subject.toString());
-        } else {
-            log.warn("Given configuration {} is not supported", configClass.toString());
-            return null;
-        }
-    }
-
-    /**
-     * Returns the singleton instance of multicast routes NIB.
-     *
-     * @return instance of multicast routes NIB
-     */
-    public static NetworkConfigNib getInstance() {
-        return NetworkConfigNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final NetworkConfigNib INSTANCE = new NetworkConfigNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/NibProfile.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/NibProfile.java
deleted file mode 100644
index 146d98a..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/NibProfile.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import java.text.SimpleDateFormat;
-
-/**
- * Basic descriptions about a single Network information Base (NIB) instance.
- */
-public class NibProfile {
-    // default false means the contents of this NIB are empty at the instantiation
-    private boolean valid = false;
-    private String date;
-    private SourceType sourceType;
-
-    public enum SourceType {
-        /**
-         * Provided by dump files.
-         */
-        FILE,
-        /**
-         * Provided by a running system.
-         */
-        SNAPSHOT
-    }
-
-    public NibProfile(long date, SourceType sourceType) {
-        this.valid = true;
-        this.date = new SimpleDateFormat("dd-MM-yyyy hh:mm").format(date);
-        this.sourceType = sourceType;
-    }
-
-    /**
-     * Returns the validity state of this NIB.
-     *
-     * @return true once this profile is initialized
-     */
-    public boolean isValid() {
-        return valid;
-    }
-
-    /**
-     * Returns the time this NIB has been filled.
-     *
-     * @return string representation for the time
-     */
-    public String date() {
-        return date;
-    }
-
-    /**
-     * Returns the type of the source used to fill this NIB.
-     *
-     * @return source type
-     */
-    public SourceType sourceType() {
-        return sourceType;
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/RouteNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/RouteNib.java
deleted file mode 100644
index 01e6e61..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/RouteNib.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.routeservice.ResolvedRoute;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for routes
- * and supports alternative functions to
- * {@link org.onosproject.routeservice.RouteService} for offline data.
- */
-public class RouteNib extends AbstractNib {
-
-    // TODO with method optimization, store into subdivided structures at the first load
-    // unresolved Route is treated as ResolvedRoute with nextHopMac null
-    Set<ResolvedRoute> routes;
-
-    // use the singleton helper to create the instance
-    protected RouteNib() {
-    }
-
-    /**
-     * Sets a set of routes.
-     *
-     * @param routes route set
-     */
-    public void setRoutes(Set<ResolvedRoute> routes) {
-        this.routes = routes;
-    }
-
-    /**
-     * Returns the set of routes.
-     *
-     * @return route set
-     */
-    public Set<ResolvedRoute> getRoutes() {
-        return routes;
-    }
-
-    /**
-     * Performs a longest prefix lookup on the given IP address.
-     *
-     * @param ip IP address to look up
-     * @return most specific matching route, if one exists
-     */
-    public Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip) {
-        return routes.stream()
-                .filter(r -> r.prefix().contains(ip))
-                .max(Comparator.comparing(r -> r.prefix().prefixLength()));
-    }
-
-    /**
-     * Returns all resolved routes stored for the given prefix, including the
-     * best selected route.
-     *
-     * @param prefix IP prefix to look up routes for
-     * @return all stored resolved routes for this prefix
-     */
-    public Collection<ResolvedRoute> getAllResolvedRoutes(IpPrefix prefix) {
-        return routes.stream()
-                .filter(r -> r.prefix().contains(prefix)
-                        && r.nextHopMac() != null
-                        && r.nextHopVlan() != null)
-                .collect(Collectors.toCollection(ArrayList::new));
-    }
-
-    /**
-     * Returns the singleton instance of multicast routes NIB.
-     *
-     * @return instance of multicast routes NIB
-     */
-    public static RouteNib getInstance() {
-        return RouteNib.SingletonHelper.INSTANCE;
-    }
-
-    private static class SingletonHelper {
-        private static final RouteNib INSTANCE = new RouteNib();
-    }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
deleted file mode 100644
index 22db007..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright 2017-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.t3.api;
-
-import com.google.common.collect.ImmutableList;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.TrafficSelector;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-/**
- * Encapsulates the result of tracing a packet (traffic selector) through
- * the current topology.
- */
-public class StaticPacketTrace {
-
-    private final TrafficSelector inPacket;
-    private final ConnectPoint in;
-    List<List<ConnectPoint>> completePaths;
-    private Map<DeviceId, List<GroupsInDevice>> outputsForDevice;
-    private Map<DeviceId, List<FlowEntry>> flowsForDevice;
-    private StringBuilder resultMessage;
-    private Pair<Host, Host> hosts;
-    private List<Boolean> success = new ArrayList<>();
-
-    /**
-     * Builds the trace with a given packet and a connect point.
-     *
-     * @param packet the packet to trace
-     * @param in     the initial connect point
-     */
-    public StaticPacketTrace(TrafficSelector packet, ConnectPoint in) {
-        this.inPacket = packet;
-        this.in = in;
-        completePaths = new ArrayList<>();
-        outputsForDevice = new HashMap<>();
-        flowsForDevice = new HashMap<>();
-        resultMessage = new StringBuilder();
-        hosts = null;
-    }
-
-    /**
-     * Builds the trace with a given packet and a connect point.
-     *
-     * @param packet the packet to trace
-     * @param in     the initial connect point
-     * @param hosts  pair of source and destination hosts
-     */
-    public StaticPacketTrace(TrafficSelector packet, ConnectPoint in, Pair<Host, Host> hosts) {
-        this.inPacket = packet;
-        this.in = in;
-        completePaths = new ArrayList<>();
-        outputsForDevice = new HashMap<>();
-        flowsForDevice = new HashMap<>();
-        resultMessage = new StringBuilder();
-        this.hosts = hosts;
-    }
-
-    /**
-     * Return the initial packet.
-     *
-     * @return the initial packet in the form of a selector.
-     */
-    public TrafficSelector getInitialPacket() {
-        return inPacket;
-    }
-
-    /**
-     * Returns the first connect point the packet came in through.
-     *
-     * @return the connect point
-     */
-    public ConnectPoint getInitialConnectPoint() {
-        return in;
-    }
-
-    /**
-     * Add a result message for the Trace.
-     *
-     * @param resultMessage the message
-     */
-    public void addResultMessage(String resultMessage) {
-        if (this.resultMessage.length() != 0) {
-            this.resultMessage.append("\n");
-        }
-        this.resultMessage.append(resultMessage);
-    }
-
-    /**
-     * Return the result message.
-     *
-     * @return the message
-     */
-    public String resultMessage() {
-        return resultMessage.toString();
-    }
-
-    /**
-     * Adds the groups for a given device.
-     *
-     * @param deviceId   the device
-     * @param outputPath the groups in device objects
-     */
-    public void addGroupOutputPath(DeviceId deviceId, GroupsInDevice outputPath) {
-        if (!outputsForDevice.containsKey(deviceId)) {
-            outputsForDevice.put(deviceId, new ArrayList<>());
-        }
-        outputsForDevice.get(deviceId).add(outputPath);
-    }
-
-    /**
-     * Returns all the possible group-based outputs for a given device.
-     *
-     * @param deviceId the device
-     * @return the list of Groups for this device.
-     */
-    public List<GroupsInDevice> getGroupOuputs(DeviceId deviceId) {
-        return outputsForDevice.get(deviceId) == null ? null : ImmutableList.copyOf(outputsForDevice.get(deviceId));
-    }
-
-    /**
-     * Adds a complete possible path.
-     *
-     * @param completePath the path
-     */
-    public void addCompletePath(List<ConnectPoint> completePath) {
-        completePaths.add(completePath);
-    }
-
-    /**
-     * Return all the possible path the packet can take through the network.
-     *
-     * @return a list of paths
-     */
-    public List<List<ConnectPoint>> getCompletePaths() {
-        return completePaths;
-    }
-
-    /**
-     * Add the flows traversed by the packet in a given device.
-     *
-     * @param deviceId the device considered
-     * @param flows    the flows
-     */
-    public void addFlowsForDevice(DeviceId deviceId, List<FlowEntry> flows) {
-        flowsForDevice.put(deviceId, flows);
-    }
-
-    /**
-     * Returns the flows matched by this trace's packet for a given device.
-     *
-     * @param deviceId the device
-     * @return the flows matched
-     */
-    public List<FlowEntry> getFlowsForDevice(DeviceId deviceId) {
-        return flowsForDevice.getOrDefault(deviceId, ImmutableList.of());
-    }
-
-    /**
-     * Return, if present, the two hosts at the endpoints of this trace.
-     *
-     * @return pair of source and destination hosts
-     */
-    public Optional<Pair<Host, Host>> getEndpointHosts() {
-        return Optional.ofNullable(hosts);
-    }
-
-    /**
-     * Sets the two hosts at the endpoints of this trace.
-     *
-     * @param endpointHosts pair of source and destination hosts
-     */
-    public void addEndpointHosts(Pair<Host, Host> endpointHosts) {
-        hosts = endpointHosts;
-    }
-
-    /**
-     * Return if all the possible paths of this trace are successful.
-     *
-     * @return true if all paths are successful
-     */
-    public boolean isSuccess() {
-        return !success.contains(false);
-    }
-
-    /**
-     * Sets if a path from this trace is successful.
-     *
-     * @param success true if a path of trace is successful.
-     */
-    public void setSuccess(boolean success) {
-        this.success.add(success);
-    }
-
-
-    @Override
-    public String toString() {
-        return "StaticPacketTrace{" +
-                "inPacket=" + inPacket +
-                ", in=" + in +
-                ", completePaths=" + completePaths +
-                ", outputsForDevice=" + outputsForDevice +
-                ", flowsForDevice=" + flowsForDevice +
-                ", resultMessage=" + resultMessage +
-                '}';
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/TroubleshootService.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/TroubleshootService.java
deleted file mode 100644
index 3ab6052..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/TroubleshootService.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2017-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.t3.api;
-
-import org.onlab.packet.EthType;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.HostId;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.t3.impl.Generator;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * API for troubleshooting services, providing static analysis of installed
- * flows and groups.
- */
-public interface TroubleshootService {
-
-    /**
-     * Requests a static trace be performed between all hosts in the network, given a type of traffic.
-     *
-     * @param type the etherType of the traffic we want to trace.
-     * @return trace result
-     */
-    List<StaticPacketTrace> pingAll(EthType.EtherType type);
-
-    /**
-     * Requests a static trace be performed between all hosts in the network, given a type of traffic.
-     *
-     * @param type the etherType of the traffic we want to trace.
-     * @return trace result
-     */
-    Generator<Set<StaticPacketTrace>> pingAllGenerator(EthType.EtherType type);
-
-    /**
-     * Requests a static trace be performed for all mcast Routes in the network.
-     *
-     * @param vlanId the vlanId configured for multicast.
-     * @return set of trace result yielded one by one.
-     */
-    Generator<Set<StaticPacketTrace>> traceMcast(VlanId vlanId);
-
-    /**
-     * Requests a static trace be performed between the two hosts in the network, given a type of traffic.
-     *
-     * @param sourceHost      source host
-     * @param destinationHost destination host
-     * @param type            the etherType of the traffic we want to trace.
-     * @return trace result
-     */
-    Set<StaticPacketTrace> trace(HostId sourceHost, HostId destinationHost, EthType.EtherType type);
-
-    /**
-     * Requests a static trace be performed for the given traffic selector
-     * starting at the given connect point.
-     *
-     * @param packet description of packet
-     * @param in     point at which packet starts
-     * @return trace result
-     */
-    StaticPacketTrace trace(TrafficSelector packet, ConnectPoint in);
-
-    /**
-     * Requests list of static trace to be performed for all mcast routes in the network.
-     *
-     * @param vlanId the vlan id configured for multicast
-     * @return list of trace result
-     */
-    List<Set<StaticPacketTrace>> getMulitcastTrace(VlanId vlanId);
-
-    /**
-     * Checks the validity of NIBs applied to the manager.
-     *
-     * @return true only if all NIBs are in the valid state.
-     */
-    boolean checkNibValidity();
-
-    /**
-     * Returns a summary describing all the NIBs applied to the manager.
-     *
-     * @return string for the summary
-     */
-    String printNibSummary();
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/package-info.java
deleted file mode 100644
index 152d568..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-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.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics API.
- */
-package org.onosproject.t3.api;
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/NibLoader.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/NibLoader.java
deleted file mode 100644
index 40690ca..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/NibLoader.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import java.io.IOException;
-
-/**
- * Common APIs for T3 CLI commands to load snapshots of the network states
- * from {@link org.onosproject.t3.api.NibProfile.SourceType} and fill the NIB.
- */
-public interface NibLoader {
-
-    /**
-     * Extracts flow-related information and fills the flow NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadFlowNib() throws IOException;
-
-    /**
-     * Extracts group-related information and fills the group NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadGroupNib() throws IOException;
-
-    /**
-     * Extracts host-related information and fills the host NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadHostNib() throws IOException;
-
-    /**
-     * Extracts link-related information and fills the link NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadLinkNib() throws IOException;
-
-    /**
-     * Extracts device-related information and fills the device NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadDeviceNib() throws IOException;
-
-    /**
-     * Extracts driver-related information and fills the driver NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadDriverNib() throws IOException;
-
-    /**
-     * Extracts mastership-related information and fills the mastership NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadMastershipNib() throws IOException;
-
-    /**
-     * Extracts edge port-related information and fills the edge port NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadEdgePortNib() throws IOException;
-
-    /**
-     * Extracts route-related information and fills the route NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadRouteNib() throws IOException;
-
-    /**
-     * Extracts network config-related information and fills the network configuration NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadNetworkConfigNib() throws IOException;
-
-    /**
-     * Extracts multicast route-related information and fills the multicast route NIB.
-     *
-     * @throws IOException  exception during possible file I/O
-     */
-    void loadMulticastRouteNib() throws IOException;
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/T3CliUtils.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/T3CliUtils.java
deleted file mode 100644
index ddbdb38..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/T3CliUtils.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.t3.cli;
-
-import org.apache.commons.lang.StringUtils;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.t3.api.GroupsInDevice;
-import org.onosproject.t3.api.StaticPacketTrace;
-
-import java.util.List;
-
-/**
- * Class containing utility methods for T3 cli.
- */
-final class T3CliUtils {
-
-    private T3CliUtils() {
-        //banning construction
-    }
-
-    private static final String FLOW_SHORT_FORMAT = "    %s, bytes=%s, packets=%s, "
-            + "table=%s, priority=%s, selector=%s, treatment=%s";
-
-    private static final String GROUP_FORMAT =
-            "   id=0x%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s, referenceCount=%s";
-    private static final String GROUP_BUCKET_FORMAT =
-            "       id=0x%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
-
-    public static final String NIB_AUTOFILLED =
-            "*** NIB is invalid. Snapshots for the NIB have been auto-filled: ***";
-    public static final String NIB_TERMINATE =
-            "*** NIB is still invalid. You can manually load it via CLI commands for T3 load and try again ***";
-
-    /**
-     * Builds a string output for the given trace for a specific level of verbosity.
-     *
-     * @param trace      the trace
-     * @param verbosity1 middle verbosity level
-     * @param verbosity2 high verbosity level
-     * @return a string representing the trace.
-     */
-    static String printTrace(StaticPacketTrace trace, boolean verbosity1, boolean verbosity2) {
-        StringBuilder tracePrint = new StringBuilder();
-        //Print based on verbosity
-        if (verbosity1) {
-            tracePrint = printTrace(trace, false, tracePrint);
-        } else if (verbosity2) {
-            tracePrint = printTrace(trace, true, tracePrint);
-        } else {
-            tracePrint.append("Paths");
-            tracePrint.append("\n");
-            List<List<ConnectPoint>> paths = trace.getCompletePaths();
-            for (List<ConnectPoint> path : paths) {
-                tracePrint.append(path);
-                tracePrint.append("\n");
-            }
-        }
-        tracePrint.append("Result: \n" + trace.resultMessage());
-        return tracePrint.toString();
-    }
-
-    //prints the trace
-    private static StringBuilder printTrace(StaticPacketTrace trace, boolean verbose, StringBuilder tracePrint) {
-        List<List<ConnectPoint>> paths = trace.getCompletePaths();
-        for (List<ConnectPoint> path : paths) {
-            tracePrint.append("Path " + path);
-            tracePrint.append("\n");
-            ConnectPoint previous = null;
-            if (path.size() == 1) {
-                ConnectPoint connectPoint = path.get(0);
-                tracePrint.append("Device " + connectPoint.deviceId());
-                tracePrint.append("\n");
-                tracePrint.append("Input from " + connectPoint);
-                tracePrint.append("\n");
-                tracePrint = printFlows(trace, verbose, connectPoint, tracePrint);
-                tracePrint = printGroups(trace, verbose, connectPoint, tracePrint);
-                tracePrint.append("\n");
-            } else {
-                for (ConnectPoint connectPoint : path) {
-                    if (previous == null || !previous.deviceId().equals(connectPoint.deviceId())) {
-                        tracePrint.append("Device " + connectPoint.deviceId());
-                        tracePrint.append("\n");
-                        tracePrint.append("    Input from " + connectPoint);
-                        tracePrint.append("\n");
-                        tracePrint = printFlows(trace, verbose, connectPoint, tracePrint);
-                    } else {
-                        tracePrint = printGroups(trace, verbose, connectPoint, tracePrint);
-                        tracePrint.append("    Output through " + connectPoint);
-                        tracePrint.append("\n");
-                    }
-                    previous = connectPoint;
-                }
-            }
-            tracePrint.append(StringUtils.leftPad("\n", 100, '-'));
-        }
-        return tracePrint;
-    }
-
-
-    //Prints the flows for a given trace and a specified level of verbosity
-    private static StringBuilder printFlows(StaticPacketTrace trace, boolean verbose, ConnectPoint connectPoint,
-                                            StringBuilder tracePrint) {
-        tracePrint.append("    Flows ");
-        tracePrint.append(trace.getFlowsForDevice(connectPoint.deviceId()).size());
-        tracePrint.append("    \n");
-        trace.getFlowsForDevice(connectPoint.deviceId()).forEach(f -> {
-            if (verbose) {
-                tracePrint.append("    " + String.format(FLOW_SHORT_FORMAT, f.state(), f.bytes(), f.packets(),
-                        f.table(), f.priority(), f.selector().criteria(),
-                        printTreatment(f.treatment())));
-                tracePrint.append("\n");
-            } else {
-                tracePrint.append(String.format("       flowId=%s, table=%s, selector=%s", f.id(), f.table(),
-                        f.selector().criteria()));
-                tracePrint.append("\n");
-            }
-        });
-        return tracePrint;
-    }
-
-    //Prints the groups for a given trace and a specified level of verbosity
-    private static StringBuilder printGroups(StaticPacketTrace trace, boolean verbose, ConnectPoint connectPoint,
-                                             StringBuilder tracePrint) {
-        List<GroupsInDevice> groupsInDevice = trace.getGroupOuputs(connectPoint.deviceId());
-        if (groupsInDevice != null) {
-            tracePrint.append("    Groups");
-            tracePrint.append("\n");
-            groupsInDevice.forEach(output -> {
-                if (output.getOutput().equals(connectPoint)) {
-                    output.getGroups().forEach(group -> {
-                        if (verbose) {
-                            tracePrint.append("    " + String.format(GROUP_FORMAT, Integer.toHexString(group.id().id()),
-                                    group.state(), group.type(), group.bytes(), group.packets(),
-                                    group.appId().name(), group.referenceCount()));
-                            tracePrint.append("\n");
-                            int i = 0;
-                            for (GroupBucket bucket : group.buckets().buckets()) {
-                                tracePrint.append("    " + String.format(GROUP_BUCKET_FORMAT,
-                                        Integer.toHexString(group.id().id()),
-                                        ++i, bucket.bytes(), bucket.packets(),
-                                        bucket.treatment().allInstructions()));
-                                tracePrint.append("\n");
-                            }
-                        } else {
-                            tracePrint.append("       groupId=" + group.id());
-                            tracePrint.append("\n");
-                        }
-                    });
-                    tracePrint.append("    Outgoing Packet " + output.getFinalPacket());
-                    tracePrint.append("\n");
-                }
-            });
-        }
-        return tracePrint;
-    }
-
-    private static String printTreatment(TrafficTreatment treatment) {
-        final String delimiter = ", ";
-        StringBuilder builder = new StringBuilder("[");
-        if (!treatment.immediate().isEmpty()) {
-            builder.append("immediate=" + treatment.immediate() + delimiter);
-        }
-        if (!treatment.deferred().isEmpty()) {
-            builder.append("deferred=" + treatment.deferred() + delimiter);
-        }
-        if (treatment.clearedDeferred()) {
-            builder.append("clearDeferred" + delimiter);
-        }
-        if (treatment.tableTransition() != null) {
-            builder.append("transition=" + treatment.tableTransition() + delimiter);
-        }
-        if (treatment.metered() != null) {
-            builder.append("meter=" + treatment.metered() + delimiter);
-        }
-        if (treatment.writeMetadata() != null) {
-            builder.append("metadata=" + treatment.writeMetadata() + delimiter);
-        }
-        // Chop off last delimiter
-        builder.replace(builder.length() - delimiter.length(), builder.length(), "");
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadFileCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadFileCommand.java
deleted file mode 100644
index 58b99d6..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadFileCommand.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.Lists;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.group.Group;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.NetworkConfigNib;
-import org.onosproject.t3.api.NibProfile;
-import org.onosproject.t3.api.RouteNib;
-import org.slf4j.Logger;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * T3 CLI command to load the NIB with dump files that represent snapshots of the network states.
- */
-@Service
-@Command(scope = "onos", name = "t3-load-file",
-        description = "Load the NIB with onos-diagnostics dump files")
-public class TroubleshootLoadFileCommand
-        extends AbstractShellCommand implements NibLoader {
-
-    private static final Logger log = getLogger(TroubleshootLoadFileCommand.class);
-
-    @Argument(index = 0, name = "rootDir", description = "Specify the location of the directory " +
-            "where the dump files of a given instance have been extracted (e.g. /tmp/onos-diags/127.0.0.1)",
-            required = true, multiValued = false)
-    @Completion(PlaceholderCompleter.class)
-    String rootDir;
-
-    @Override
-    protected void doExecute() {
-
-        if (!rootDir.endsWith("/")) {
-            rootDir = rootDir + "/";
-        }
-        print("Load target files in: %s", rootDir);
-
-        try {
-            // names of files to read are defined in the onos-diagnostics script
-            loadFlowNib();
-            loadGroupNib();
-            loadLinkNib();
-            loadHostNib();
-            loadDeviceNib();
-            loadDriverNib();
-            loadMastershipNib();
-            loadEdgePortNib();
-            loadRouteNib();
-            loadNetworkConfigNib();
-            loadMulticastRouteNib();
-
-        } catch (IOException e) {
-            print("Error in creating NIB: %s", e.getMessage());
-            log.error("Nib creation error", e);
-            return;
-        }
-
-        // ensured no errors in file loading. so make them available officially
-        Lists.newArrayList(FlowNib.getInstance(), GroupNib.getInstance(), LinkNib.getInstance(),
-                HostNib.getInstance(), DeviceNib.getInstance(), DriverNib.getInstance(),
-                MastershipNib.getInstance(), EdgePortNib.getInstance(), RouteNib.getInstance(),
-                NetworkConfigNib.getInstance(), MulticastRouteNib.getInstance())
-                .forEach(nib -> {
-                    // specify creation time and source which the NIB is filled with
-                    nib.setProfile(new NibProfile(System.currentTimeMillis(), NibProfile.SourceType.FILE));
-                    NibProfile profile = nib.getProfile();
-                    print(String.format(
-                            nib.getClass().getSimpleName() + " created %s from %s",
-                            profile.date(), profile.sourceType()));
-                });
-    }
-
-    @Override
-    public void loadFlowNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "flows.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Set<FlowEntry> flows = new HashSet<>();
-
-        List<ObjectNode> flowNodeList = new ArrayList<>();
-        jsonTree.forEach(jsonNode -> {
-            ArrayNode flowArrayNode = (ArrayNode) jsonNode.get("flows");
-            Lists.newArrayList(flowArrayNode.iterator())
-                    .forEach(flowNode -> flowNodeList.add((ObjectNode) flowNode));
-        });
-
-        // TODO: future plan for the new APIs of the flow rule service that returns raw flows or normalized flows
-        flowNodeList.forEach(flowNode -> {
-            FlowEntry flow;
-            try {
-                flow = codec(FlowEntry.class).decode(flowNode, this);
-            } catch (IllegalArgumentException e) {
-                log.warn("T3 in offline mode ignores reading extension fields of this flow to avoid decoding error");
-                ObjectNode extensionRemoved = removeExtension(flowNode);
-                flow = codec(FlowEntry.class).decode(extensionRemoved, this);
-            }
-            flows.add(flow);
-        });
-
-        FlowNib flowNib = FlowNib.getInstance();
-        flowNib.setFlows(flows);
-
-        stream.close();
-    }
-
-    /**
-     * Remove JSON nodes for extension instructions of a flow.
-     * This effectively allows T3 in offline mode to ignore extension fields of flows to avoid "device not found" error.
-     * See decodeExtension() in {@link org.onosproject.codec.impl.DecodeInstructionCodecHelper}.
-     *
-     * @param flowNode  the json node representing a flow
-     * @return          json node with removed extensions
-     */
-    private ObjectNode removeExtension(ObjectNode flowNode) {
-
-        // TODO: decoding extension instructions of offline (dumped) flows is not supported by T3 for now
-        ArrayNode extensionRemoved = mapper().createArrayNode();
-        ArrayNode instructionArrayNode = (ArrayNode) flowNode.get("treatment").get("instructions");
-        instructionArrayNode.forEach(instrNode -> {
-            String instrType = instrNode.get("type").asText();
-            if (!instrType.equals(Instruction.Type.EXTENSION.name())) {
-                extensionRemoved.add(instrNode);
-            }
-        });
-        ((ObjectNode) flowNode.get("treatment")).replace("instructions", extensionRemoved);
-
-        return flowNode;
-    }
-
-    @Override
-    public void loadGroupNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "groups.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Set<Group> groups = new HashSet<>();
-
-        // note: the parsing structure depends on GroupsListCommand
-        groups.addAll(codec(Group.class).decode((ArrayNode) jsonTree, this));
-
-        GroupNib groupNib = GroupNib.getInstance();
-        groupNib.setGroups(groups);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadLinkNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "links.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Set<Link> links = new HashSet<>();
-
-        // note: the parsing structure depends on LinksListCommand
-        links.addAll(codec(Link.class).decode((ArrayNode) jsonTree, this));
-
-        LinkNib linkNib = LinkNib.getInstance();
-        linkNib.setLinks(links);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadHostNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "hosts.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Set<Host> hosts = new HashSet<>();
-
-        // note: the parsing structure depends on HostsListCommand
-        hosts.addAll(codec(Host.class).decode((ArrayNode) jsonTree, this));
-
-        HostNib hostNib = HostNib.getInstance();
-        hostNib.setHosts(hosts);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadDeviceNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "ports.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Map<Device, Set<Port>> devicePortMap = new HashMap<>();
-
-        // note: the parsing structure depends on DevicePortsListCommand
-        jsonTree.forEach(jsonNode -> {
-            Device device = codec(Device.class).decode(
-                    (ObjectNode) jsonNode.get("device"), this);
-            Set<Port> ports = new HashSet<>(codec(Port.class).decode(
-                    (ArrayNode) jsonNode.get("ports"), this));
-            devicePortMap.put(device, ports);
-        });
-
-        DeviceNib deviceNib = DeviceNib.getInstance();
-        deviceNib.setDevicePortMap(devicePortMap);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadDriverNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "device-drivers.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Map<DeviceId, String> deviceDriverMap = new HashMap<>();
-
-        // note: the parsing structure depends on DeviceDriversCommand
-        jsonTree.fields().forEachRemaining(e -> {
-            deviceDriverMap.put(DeviceId.deviceId(e.getKey()), e.getValue().asText());
-        });
-
-        DriverNib driverNib = DriverNib.getInstance();
-        driverNib.setDeviceDriverMap(deviceDriverMap);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadMastershipNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "masters.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Map<DeviceId, NodeId> deviceMasterMap = new HashMap<>();
-
-        // note: the parsing structure depends on MastersListCommand
-        jsonTree.forEach(jsonNode -> {
-            ArrayNode devicesNode = ((ArrayNode) jsonNode.get("devices"));
-            devicesNode.forEach(deviceNode -> {
-                // a device is connected to only one master node at a time
-                deviceMasterMap.put(
-                        DeviceId.deviceId(deviceNode.asText()),
-                        NodeId.nodeId(jsonNode.get("id").asText()));
-            });
-        });
-
-        MastershipNib mastershipNib = MastershipNib.getInstance();
-        mastershipNib.setDeviceMasterMap(deviceMasterMap);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadEdgePortNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "edge-ports.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Map<DeviceId, Set<ConnectPoint>> edgePorts = new HashMap<>();
-
-        // note: the parsing structure depends on EdgePortsListCommand
-        jsonTree.forEach(jsonNode -> {
-            DeviceId deviceId = DeviceId.deviceId(jsonNode.fieldNames().next());
-            PortNumber portNumber = PortNumber.portNumber(
-                    jsonNode.get(deviceId.toString()).asText());
-            if (!edgePorts.containsKey(deviceId)) {
-                edgePorts.put(deviceId, new HashSet<>());
-            }
-            edgePorts.get(deviceId).add(new ConnectPoint(deviceId, portNumber));
-        });
-
-        EdgePortNib edgePortNib = EdgePortNib.getInstance();
-        edgePortNib.setEdgePorts(edgePorts);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadRouteNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "routes.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Set<ResolvedRoute> routes = new HashSet<>();
-
-        // note: the parsing structure depends on RoutesListCommand
-        jsonTree.fields().forEachRemaining(e -> {
-            ArrayNode routesNode = (ArrayNode) e.getValue();
-            routesNode.forEach(routeNode -> {
-                Route route = codec(Route.class).decode((ObjectNode) routeNode, this);
-                // parse optional fields needed for ResolvedRoute
-                MacAddress nextHopMac = (null == routeNode.get("nextHopMac")) ?
-                        null : MacAddress.valueOf(routeNode.get("nextHopMac").asText());
-                VlanId nextHopVlan = (null == routeNode.get("nextHopVlan")) ?
-                        null : VlanId.vlanId(routeNode.get("nextHopVlan").asText());
-                routes.add(new ResolvedRoute(route, nextHopMac, nextHopVlan));
-            });
-        });
-
-        RouteNib routeNib = RouteNib.getInstance();
-        routeNib.setRoutes(routes);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadNetworkConfigNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "netcfg.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Map<String, Config> portConfigMap = new HashMap<>();
-        Map<String, Config> deviceConfigMap = new HashMap<>();
-
-        // note: the parsing structure depends on NetworkConfigCommand
-        // TODO: improve the code quality by referring to target json
-        jsonTree.fields().forEachRemaining(e -> {
-            if (e.getKey().equals("ports")) {
-                JsonNode portConfigsNode = e.getValue();
-                portConfigsNode.fields().forEachRemaining(portConfigEntry -> {
-                    String key = portConfigEntry.getKey();
-                    InterfaceConfig config = new InterfaceConfig();
-                    config.init(ConnectPoint.fromString(key), "interfaces",
-                            portConfigEntry.getValue().get("interfaces"), mapper(), null);
-                    portConfigMap.put(key, config);
-                });
-            } else if (e.getKey().equals("devices")) {
-                JsonNode deviceConfigsNode = e.getValue();
-                deviceConfigsNode.fields().forEachRemaining(deviceConfigEntry -> {
-                    String key = deviceConfigEntry.getKey();
-                    SegmentRoutingDeviceConfig config = new SegmentRoutingDeviceConfig();
-                    config.init(DeviceId.deviceId(key), "segmentrouting",
-                            deviceConfigEntry.getValue().get("segmentrouting"), mapper(), null);
-                    deviceConfigMap.put(key, config);
-                });
-            } else {
-                log.warn("Given configuration subject {} is not supported", e.getKey());
-            }
-        });
-
-        NetworkConfigNib networkConfigNib = NetworkConfigNib.getInstance();
-        networkConfigNib.setPortConfigMap(portConfigMap);
-        networkConfigNib.setDeviceConfigMap(deviceConfigMap);
-
-        stream.close();
-    }
-
-    @Override
-    public void loadMulticastRouteNib() throws IOException {
-        InputStream stream = new FileInputStream(new File(rootDir + "mcast-host-show.json"));
-        JsonNode jsonTree = mapper().readTree(stream);
-        Map<McastRoute, McastRouteData> mcastRoutes = new HashMap<>();
-
-        // note: the parsing structure depends on McastShowHostCommand
-        jsonTree.forEach(mcastRouteNode -> {
-            // use McastHostRouteCodec to decode McastRoute
-            McastRoute mcastRoute = codec(McastRoute.class)
-                    .decode((ObjectNode) mcastRouteNode, this);
-            // create McastRouteData that stores sources and sinks of McastRoute
-            McastRouteData mcastRouteData = McastRouteData.empty();
-            if (mcastRouteNode.get("sources") != null) {
-                JsonNode sourcesNode = mcastRouteNode.get("sources");
-                sourcesNode.fields().forEachRemaining(sourceEntry -> {
-                    HostId hostId = HostId.hostId(sourceEntry.getKey());
-                    Set<ConnectPoint> sources = mapper().convertValue(
-                            sourceEntry.getValue(), new TypeReference<Set<ConnectPoint>>() { });
-                    mcastRouteData.addSources(hostId, sources);
-                });
-            }
-            if (mcastRouteNode.get("sinks") != null) {
-                JsonNode sinksNode = mcastRouteNode.get("sinks");
-                sinksNode.fields().forEachRemaining(sinkEntry -> {
-                    HostId hostId = HostId.hostId(sinkEntry.getKey());
-                    Set<ConnectPoint> sinks = mapper().convertValue(
-                            sinkEntry.getValue(), new TypeReference<Set<ConnectPoint>>() { });
-                    mcastRouteData.addSinks(hostId, sinks);
-                });
-            }
-            mcastRoutes.put(mcastRoute, mcastRouteData);
-        });
-
-        MulticastRouteNib mcastRouteNib = MulticastRouteNib.getInstance();
-        mcastRouteNib.setMcastRoutes(mcastRoutes);
-
-        stream.close();
-    }
-
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadSnapshotCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadSnapshotCommand.java
deleted file mode 100644
index 9a6b20b..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadSnapshotCommand.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.mcast.api.MulticastRouteService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.DriverService;
-import org.onosproject.net.edge.EdgePortService;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupService;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteService;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.NetworkConfigNib;
-import org.onosproject.t3.api.NibProfile;
-import org.onosproject.t3.api.RouteNib;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * T3 CLI command to load the NIB with snapshots of the network states that are fetched from ONOS stores.
- */
-@Service
-@Command(scope = "onos", name = "t3-load-snapshot",
-        description = "Load the NIB with the network states stored in the ONOS instance where the T3 is running")
-public class TroubleshootLoadSnapshotCommand
-        extends AbstractShellCommand implements NibLoader {
-
-    @Override
-    protected void doExecute() {
-
-        print("Load current network states from ONOS stores");
-
-        loadFlowNib();
-        loadGroupNib();
-        loadLinkNib();
-        loadHostNib();
-        loadDeviceNib();
-        loadDriverNib();
-        loadMastershipNib();
-        loadEdgePortNib();
-        loadRouteNib();
-        loadNetworkConfigNib();
-        loadMulticastRouteNib();
-
-        Lists.newArrayList(FlowNib.getInstance(), GroupNib.getInstance(), LinkNib.getInstance(),
-                HostNib.getInstance(), DeviceNib.getInstance(), DriverNib.getInstance(),
-                MastershipNib.getInstance(), EdgePortNib.getInstance(), RouteNib.getInstance(),
-                NetworkConfigNib.getInstance(), MulticastRouteNib.getInstance())
-                .forEach(nib -> {
-                    // specify creation time and source which the NIB is filled with
-                    nib.setProfile(new NibProfile(System.currentTimeMillis(), NibProfile.SourceType.SNAPSHOT));
-                    NibProfile profile = nib.getProfile();
-                    print(String.format(
-                            nib.getClass().getSimpleName() + " created %s from %s",
-                            profile.date(), profile.sourceType()));
-                });
-    }
-
-    @Override
-    public void loadFlowNib() {
-        FlowRuleService flowRuleService = get(FlowRuleService.class);
-        DeviceService deviceService = get(DeviceService.class);
-        Set<FlowEntry> flows = new HashSet<>();
-
-        Lists.newArrayList(deviceService.getDevices().iterator())
-                .forEach(device -> flows.addAll(Lists.newArrayList(
-                        flowRuleService.getFlowEntries(device.id()))));
-
-        FlowNib flowNib = FlowNib.getInstance();
-        flowNib.setFlows(flows);
-    }
-
-    @Override
-    public void loadGroupNib() {
-        GroupService groupService = get(GroupService.class);
-        DeviceService deviceService = get(DeviceService.class);
-        Set<Group> groups = new HashSet<>();
-
-        Lists.newArrayList(deviceService.getDevices().iterator())
-                .forEach(device -> groups.addAll(Lists.newArrayList(
-                        groupService.getGroups(device.id()))));
-
-        GroupNib groupNib = GroupNib.getInstance();
-        groupNib.setGroups(groups);
-    }
-
-    @Override
-    public void loadLinkNib() {
-        LinkService linkService = get(LinkService.class);
-        Set<Link> links = new HashSet<>();
-
-        links.addAll(Lists.newArrayList(linkService.getLinks()));
-
-        LinkNib linkNib = LinkNib.getInstance();
-        linkNib.setLinks(links);
-    }
-
-    @Override
-    public void loadHostNib() {
-        HostService hostService = get(HostService.class);
-        Set<Host> hosts = new HashSet<>();
-
-        hosts.addAll(Lists.newArrayList(hostService.getHosts()));
-
-        HostNib hostNib = HostNib.getInstance();
-        hostNib.setHosts(hosts);
-    }
-
-    @Override
-    public void loadDeviceNib() {
-        DeviceService deviceService = get(DeviceService.class);
-        Map<Device, Set<Port>> devicePortMap = new HashMap<>();
-
-        Lists.newArrayList(deviceService.getDevices().iterator())
-                .forEach(device -> {
-                    // current DeviceNib impl. checks the availability of devices from their annotations
-                    DefaultAnnotations annotations = DefaultAnnotations.builder()
-                            .set("available", String.valueOf(deviceService.isAvailable(device.id()))).build();
-                    DefaultDevice annotated = new DefaultDevice(device.providerId(), device.id(), device.type(),
-                            device.manufacturer(), device.hwVersion(), device.swVersion(), device.serialNumber(),
-                            device.chassisId(), annotations);
-                    devicePortMap.put(annotated, Sets.newHashSet(deviceService.getPorts(device.id())));
-                });
-
-        DeviceNib deviceNib = DeviceNib.getInstance();
-        deviceNib.setDevicePortMap(devicePortMap);
-    }
-
-    @Override
-    public void loadDriverNib() {
-        DriverService driverService = get(DriverService.class);
-        Map<DeviceId, String> deviceDriverMap = driverService.getDeviceDrivers();
-
-        DriverNib driverNib = DriverNib.getInstance();
-        driverNib.setDeviceDriverMap(deviceDriverMap);
-    }
-
-    @Override
-    public void loadMastershipNib() {
-        MastershipService mastershipService = get(MastershipService.class);
-        DeviceService deviceService = get(DeviceService.class);
-        Map<DeviceId, NodeId> deviceMasterMap = new HashMap<>();
-
-        Lists.newArrayList(deviceService.getDevices().iterator())
-                .forEach(device -> deviceMasterMap.put(device.id(), mastershipService.getMasterFor(device.id())));
-
-        MastershipNib mastershipNib = MastershipNib.getInstance();
-        mastershipNib.setDeviceMasterMap(deviceMasterMap);
-    }
-
-    @Override
-    public void loadEdgePortNib() {
-        EdgePortService edgePortService = get(EdgePortService.class);
-        DeviceService deviceService = get(DeviceService.class);
-        Map<DeviceId, Set<ConnectPoint>> edgePorts = new HashMap<>();
-
-        Lists.newArrayList(deviceService.getDevices().iterator())
-                .forEach(device -> edgePorts.put(device.id(), Sets.newHashSet(edgePortService.getEdgePoints())));
-
-        EdgePortNib edgePortNib = EdgePortNib.getInstance();
-        edgePortNib.setEdgePorts(edgePorts);
-    }
-
-    @Override
-    public void loadRouteNib() {
-        RouteService routeService = get(RouteService.class);
-        Set<ResolvedRoute> routes = new HashSet<>();
-
-        Lists.newArrayList(routeService.getRouteTables())
-                .forEach(routeTableId -> routes.addAll(routeService.getResolvedRoutes(routeTableId)));
-
-        RouteNib routeNib = RouteNib.getInstance();
-        routeNib.setRoutes(routes);
-    }
-
-    @Override
-    public void loadNetworkConfigNib() {
-        NetworkConfigService networkConfigService = get(NetworkConfigService.class);
-        DeviceService deviceService = get(DeviceService.class);
-
-        // Map of str ConnectPoint : InterfaceConfig
-        Map<String, Config> portConfigMap = new HashMap<>();
-        Lists.newArrayList(deviceService.getDevices().iterator())
-                .forEach(device -> deviceService.getPorts(device.id())
-                        .forEach(port -> {
-                            ConnectPoint cp = new ConnectPoint(device.id(), port.number());
-                            portConfigMap.put(cp.toString(), networkConfigService.getConfig(cp, InterfaceConfig.class));
-                        }));
-
-        // Map of str DeviceId : SegmentRoutingDeviceConfig
-        Map<String, Config> deviceConfigMap = new HashMap<>();
-        Lists.newArrayList(deviceService.getDevices().iterator())
-                .forEach(device -> deviceConfigMap.put(device.id().toString(),
-                        networkConfigService.getConfig(device.id(), SegmentRoutingDeviceConfig.class)));
-
-        NetworkConfigNib networkConfigNib = NetworkConfigNib.getInstance();
-        networkConfigNib.setPortConfigMap(portConfigMap);
-        networkConfigNib.setDeviceConfigMap(deviceConfigMap);
-    }
-
-    @Override
-    public void loadMulticastRouteNib() {
-        MulticastRouteService mcastRouteService = get(MulticastRouteService.class);
-        Map<McastRoute, McastRouteData> mcastRoutes = new HashMap<>();
-
-        Lists.newArrayList(mcastRouteService.getRoutes())
-                .forEach(mcastRoute -> mcastRoutes.put(mcastRoute, mcastRouteService.routeData(mcastRoute)));
-
-        MulticastRouteNib mcastRouteNib = MulticastRouteNib.getInstance();
-        mcastRouteNib.setMcastRoutes(mcastRoutes);
-    }
-
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootMcastCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootMcastCommand.java
deleted file mode 100644
index d635c23..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootMcastCommand.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2018-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.t3.cli;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.onosproject.t3.impl.Generator;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Starts a Static Packet Trace for all the multicast routes in the system and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot-mcast",
-        description = "Traces all the mcast routes present in the system")
-public class TroubleshootMcastCommand extends AbstractShellCommand {
-
-    @Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each mcast route")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity1 = false;
-
-    @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs middle level details of every trace")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity2 = false;
-
-    @Option(name = "-vvv", aliases = "--veryveryverbose", description = "Outputs complete details of every trace")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity3 = false;
-
-    @Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
-    @Completion(PlaceholderCompleter.class)
-    String vlan = "None";
-
-
-    @Override
-    protected void doExecute() {
-        TroubleshootService service = get(TroubleshootService.class);
-        if (!service.checkNibValidity()) {
-            // if the NIB is found invalid, fill it with the current network states so that this command can proceed
-            print(T3CliUtils.NIB_AUTOFILLED);
-            TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
-            cmd.doExecute();
-            if (!service.checkNibValidity()) {
-                // if the NIB is still invalid even after auto-filled snapshots, stop and warn
-                print(T3CliUtils.NIB_TERMINATE);
-                return;
-            }
-        } else {
-            print(service.printNibSummary());
-        }
-
-        print("Tracing all Multicast routes in the System");
-
-        //Create the generator for the list of traces.
-        VlanId vlanId = vlan == null || vlan.isEmpty() ? VlanId.NONE : VlanId.vlanId(vlan);
-        Generator<Set<StaticPacketTrace>> generator = service.traceMcast(vlanId);
-        int totalTraces = 0;
-        List<StaticPacketTrace> failedTraces = new ArrayList<>();
-        StaticPacketTrace previousTrace = null;
-        while (generator.iterator().hasNext()) {
-            totalTraces++;
-            //Print also Route if possible or packet
-            Set<StaticPacketTrace> traces = generator.iterator().next();
-            if (!verbosity1 && !verbosity2 && !verbosity3) {
-                for (StaticPacketTrace trace : traces) {
-                    previousTrace = printTrace(previousTrace, trace);
-                    if (!trace.isSuccess()) {
-                        print("Failure: %s", trace.resultMessage());
-                        failedTraces.add(trace);
-                    } else {
-                        print(trace.resultMessage());
-                    }
-                }
-            } else {
-                traces.forEach(trace -> {
-                    print("Tracing packet: %s", trace.getInitialPacket());
-                    print("%s", T3CliUtils.printTrace(trace, verbosity2, verbosity3));
-                    print("%s", StringUtils.rightPad("", 125, '-'));
-                });
-            }
-        }
-
-        if (!verbosity1 && !verbosity2 && !verbosity3) {
-            if (failedTraces.size() != 0) {
-                print("%s", StringUtils.rightPad("", 125, '-'));
-                print("Failed Traces: %s", failedTraces.size());
-            }
-            previousTrace = null;
-            for (StaticPacketTrace trace : failedTraces) {
-                previousTrace = printTrace(previousTrace, trace);
-                print("Failure: %s", trace.resultMessage());
-            }
-            print("%s", StringUtils.rightPad("", 125, '-'));
-            print("Summary");
-            print("Total Traces %s, errors %s", totalTraces, failedTraces.size());
-            print("%s", StringUtils.rightPad("", 125, '-'));
-        }
-
-    }
-
-    private StaticPacketTrace printTrace(StaticPacketTrace previousTrace, StaticPacketTrace trace) {
-        if (previousTrace == null || !previousTrace.equals(trace)) {
-            print("%s", StringUtils.rightPad("", 125, '-'));
-            previousTrace = trace;
-            ConnectPoint initialConnectPoint = trace.getInitialConnectPoint();
-            TrafficSelector initialPacket = trace.getInitialPacket();
-            boolean isIPv4 = ((EthTypeCriterion) initialPacket.getCriterion(Criterion.Type.ETH_TYPE))
-                    .ethType().equals(EthType.EtherType.IPV4.ethType()
-                    );
-            IpPrefix group = ((IPCriterion) (isIPv4 ? trace.getInitialPacket()
-                    .getCriterion(Criterion.Type.IPV4_DST) : trace.getInitialPacket()
-                    .getCriterion(Criterion.Type.IPV6_DST))).ip();
-            print("Source %s, group %s", initialConnectPoint, group);
-        }
-        StringBuilder destinations = new StringBuilder();
-        if (trace.getCompletePaths().size() > 1) {
-            destinations.append("Sinks: ");
-        } else {
-            destinations.append("Sink: ");
-        }
-        trace.getCompletePaths().forEach(path -> {
-            destinations.append(path.get(path.size() - 1) + " ");
-        });
-        print("%s", destinations.toString());
-        return previousTrace;
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllCommand.java
deleted file mode 100644
index e61a533..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllCommand.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2018-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.t3.cli;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.EthTypeCompleter;
-import org.onosproject.net.Host;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.onosproject.t3.impl.Generator;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import static java.lang.Thread.sleep;
-import static org.onlab.packet.EthType.EtherType;
-
-/**
- * Starts a Static Packet Trace for a given input and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot-pingall",
-        description = "Traces a ping between all hosts in the system of a given ETH type")
-public class TroubleshootPingAllCommand extends AbstractShellCommand {
-
-    private static final String FMT_SHORT =
-            "id=%s, mac=%s, locations=%s, vlan=%s, ip(s)=%s";
-
-    @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
-    @Completion(EthTypeCompleter.class)
-    String ethType = "ipv4";
-
-    @Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each host to host combination")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity1 = false;
-
-    @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs details of every trace")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity2 = false;
-
-    @Option(name = "-d", aliases = "--delay", description = "delay between host to host trace display")
-    @Completion(PlaceholderCompleter.class)
-    private long delay = 0;
-
-    @Override
-    protected void doExecute() {
-        TroubleshootService service = get(TroubleshootService.class);
-        if (!service.checkNibValidity()) {
-            // if the NIB is found invalid, fill it with the current network states so that this command can proceed
-            print(T3CliUtils.NIB_AUTOFILLED);
-            TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
-            cmd.doExecute();
-            if (!service.checkNibValidity()) {
-                // if the NIB is still invalid even after auto-filled snapshots, stop and warn
-                print(T3CliUtils.NIB_TERMINATE);
-                return;
-            }
-        } else {
-            print(service.printNibSummary());
-        }
-
-        EtherType type = EtherType.valueOf(ethType.toUpperCase());
-
-        print("Tracing between all %s hosts", ethType);
-
-        if (!type.equals(EtherType.IPV4) && !type.equals(EtherType.IPV6)) {
-            print("Command only support IPv4 or IPv6");
-        } else {
-            //Create the generator for the list of traces.
-            Generator<Set<StaticPacketTrace>> generator = service.pingAllGenerator(type);
-            Host previousHost = null;
-            int totalTraces = 0;
-            List<StaticPacketTrace> failedTraces = new ArrayList<>();
-            boolean ipv4 = type.equals(EtherType.IPV4);
-            while (generator.iterator().hasNext()) {
-                Set<StaticPacketTrace> traces = generator.iterator().next();
-                totalTraces++;
-                for (StaticPacketTrace trace : traces) {
-                    //no verbosity is mininet style output
-                    if (!verbosity1 && !verbosity2) {
-                        if (trace.getEndpointHosts().isPresent()) {
-                            Host src = trace.getEndpointHosts().get().getLeft();
-                            if (previousHost == null || !previousHost.equals(src)) {
-                                print("%s", StringUtils.rightPad("", 125, '-'));
-                                previousHost = printSrc(trace, ipv4, src);
-                            }
-                            String host = getDstString(trace, ipv4, src);
-                            if (!trace.isSuccess()) {
-                                host = host + " " + trace.resultMessage();
-                                failedTraces.add(trace);
-                            }
-                            print("%s", host);
-                        }
-                    } else {
-                        print("%s", StringUtils.leftPad("", 125, '-'));
-
-                        if (trace.getInitialPacket() != null) {
-                            if (verbosity1) {
-                                printResultOnly(trace, ipv4);
-                            } else if (verbosity2) {
-                                printVerbose(trace);
-                            }
-                        } else {
-                            if (trace.getEndpointHosts().isPresent()) {
-                                Host source = trace.getEndpointHosts().get().getLeft();
-                                Host destination = trace.getEndpointHosts().get().getRight();
-                                print("Source %s --> Destination %s", source.id(), destination.id());
-                            }
-                            print("Error in obtaining trace: %s", trace.resultMessage());
-                        }
-                    }
-                }
-                try {
-                    sleep(delay);
-                } catch (InterruptedException e) {
-                    log.debug("interrupted while sleep");
-                }
-            }
-            print("%s", StringUtils.rightPad("", 125, '-'));
-            print("Failed Traces: %s", failedTraces.size());
-            print("%s", StringUtils.rightPad("", 125, '-'));
-            failedTraces.forEach(t -> {
-                if (t.getEndpointHosts().isPresent()) {
-                    printSrc(t, ipv4, t.getEndpointHosts().get().getLeft());
-                    String dst = getDstString(t, ipv4, t.getEndpointHosts().get().getRight());
-                    dst = dst + " " + t.resultMessage();
-                    print("%s", dst);
-                    print("%s", StringUtils.rightPad("", 125, '-'));
-                }
-            });
-            print("Summary");
-            print("Total Traces %s, errors %s", totalTraces, failedTraces.size());
-        }
-    }
-
-    private String getDstString(StaticPacketTrace trace, boolean ipv4, Host src) {
-        String host;
-        IpAddress ipAddress = getIpAddress(trace, ipv4, src, false);
-        if (ipAddress == null) {
-            host = String.format("       %s %s", trace.getEndpointHosts().get().getRight().id(),
-                    trace.isSuccess());
-        } else {
-            host = String.format("       %s (%s) %s",
-                    trace.getEndpointHosts().get().getRight().id(), ipAddress,
-                    trace.isSuccess());
-        }
-        return host;
-    }
-
-    private Host printSrc(StaticPacketTrace trace, boolean ipv4, Host src) {
-        Host previousHost;
-        IpAddress ipAddress = getIpAddress(trace, ipv4, src, true);
-        if (ipAddress == null) {
-            print("%s", src.id() + " -->");
-        } else {
-            print("%s (%s) -->", src.id(), ipAddress);
-        }
-        previousHost = src;
-        return previousHost;
-    }
-
-    private IpAddress getIpAddress(StaticPacketTrace trace, boolean ipv4, Host host, boolean src) {
-        IpAddress ipAddress;
-        if (ipv4) {
-            Criterion.Type type = src ? Criterion.Type.IPV4_SRC : Criterion.Type.IPV4_DST;
-            if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
-                ipAddress = ((IPCriterion) trace.getInitialPacket()
-                        .getCriterion(type)).ip().address();
-            } else {
-                ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp4)
-                        .findAny().orElse(null);
-            }
-        } else {
-            Criterion.Type type = src ? Criterion.Type.IPV6_SRC : Criterion.Type.IPV6_DST;
-            if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
-                ipAddress = ((IPCriterion) trace.getInitialPacket()
-                        .getCriterion(type)).ip().address();
-            } else {
-                ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp6)
-                        .findAny().orElse(null);
-            }
-        }
-        return ipAddress;
-    }
-
-    private void printResultOnly(StaticPacketTrace trace, boolean ipv4) {
-        if (trace.getEndpointHosts().isPresent()) {
-            Host source = trace.getEndpointHosts().get().getLeft();
-            Host destination = trace.getEndpointHosts().get().getRight();
-            IpAddress srcIP;
-            IpAddress dstIP;
-            if (ipv4 && trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC) != null) {
-                srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC)).ip().address();
-                dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST)).ip().address();
-                print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
-            } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC) != null) {
-                srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC)).ip().address();
-                dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST)).ip().address();
-                print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
-            } else {
-                print("Source %s --> Destination %s", source.id(), destination.id());
-            }
-            print("%s", trace.resultMessage());
-        } else {
-            print("Can't gather host information from trace");
-            print("%s", trace.resultMessage());
-        }
-    }
-
-    private void printVerbose(StaticPacketTrace trace) {
-        if (trace.getEndpointHosts().isPresent()) {
-            Host source = trace.getEndpointHosts().get().getLeft();
-            print("Source host %s", printHost(source));
-            Host destination = trace.getEndpointHosts().get().getRight();
-            print("Destination host %s", printHost(destination));
-        }
-        print("%s", trace.getInitialPacket());
-        print("%s", T3CliUtils.printTrace(trace, false, false));
-    }
-
-    private String printHost(Host host) {
-        return String.format(FMT_SHORT, host.id(), host.mac(),
-                host.locations(),
-                host.vlan(), host.ipAddresses());
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java
deleted file mode 100644
index 66f5749..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2018-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.t3.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.EthTypeCompleter;
-import org.onosproject.cli.net.HostIdCompleter;
-import org.onosproject.net.HostId;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-
-import java.util.Set;
-
-import static org.onlab.packet.EthType.EtherType;
-
-/**
- * Starts a Static Packet Trace for a given input and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot-simple",
-        description = "Given two hosts troubleshoots flows and groups between them, in case of segment routing")
-public class TroubleshootSimpleTraceCommand extends AbstractShellCommand {
-
-    // OSGi workaround to introduce package dependency
-    HostIdCompleter completer;
-    @Argument(index = 0, name = "one", description = "One host ID",
-            required = true, multiValued = false)
-    @Completion(HostIdCompleter.class)
-    String srcHost = null;
-
-    @Argument(index = 1, name = "two", description = "Another host ID",
-            required = true, multiValued = false)
-    @Completion(HostIdCompleter.class)
-    String dstHost = null;
-
-    @Option(name = "-v", aliases = "--verbose", description = "Outputs complete path")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity1 = false;
-
-    @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs flows and groups for every device")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity2 = false;
-
-    @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
-    @Completion(EthTypeCompleter.class)
-    String ethType = "ipv4";
-
-    @Override
-    protected void doExecute() {
-        TroubleshootService service = get(TroubleshootService.class);
-        if (!service.checkNibValidity()) {
-            // if the NIB is found invalid, fill it with the current network states so that this command can proceed
-            print(T3CliUtils.NIB_AUTOFILLED);
-            TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
-            cmd.doExecute();
-            if (!service.checkNibValidity()) {
-                // if the NIB is still invalid even after auto-filled snapshots, stop and warn
-                print(T3CliUtils.NIB_TERMINATE);
-                return;
-            }
-        } else {
-            print(service.printNibSummary());
-        }
-
-        if (srcHost.equals(dstHost)) {
-            print("Source and destination are same. Use different hosts");
-            return;
-        }
-
-        EtherType type = EtherType.valueOf(ethType.toUpperCase());
-
-        //Printing the traced hosts
-        print("Tracing between: %s and %s", srcHost, dstHost);
-
-        //Build the traces
-        Set<StaticPacketTrace> traces = service.trace(HostId.hostId(srcHost), HostId.hostId(dstHost), type);
-        traces.forEach(trace -> {
-            if (trace.getInitialPacket() != null) {
-                print("Tracing Packet: %s", trace.getInitialPacket());
-                print("%s", T3CliUtils.printTrace(trace, verbosity1, verbosity2));
-            } else {
-                print("Cannot obtain trace between %s and %s", srcHost, dstHost);
-                print("Reason: %s", trace.resultMessage());
-            }
-        });
-
-
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java
deleted file mode 100644
index db7d69f..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 2018-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.t3.cli;
-
-import com.google.common.base.Preconditions;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.TpPort;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.ConnectPointCompleter;
-import org.onosproject.cli.net.EthTypeCompleter;
-import org.onosproject.cli.net.IpProtocolCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-
-import static org.onlab.packet.EthType.EtherType;
-
-/**
- * Starts a Static Packet Trace for a given input and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot",
-        description = "troubleshoots flows and groups between source and destination")
-public class TroubleshootTraceCommand extends AbstractShellCommand {
-
-
-    private static final String FLOW_SHORT_FORMAT = "    %s, bytes=%s, packets=%s, "
-            + "table=%s, priority=%s, selector=%s, treatment=%s";
-
-    private static final String GROUP_FORMAT =
-            "   id=0x%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s, referenceCount=%s";
-    private static final String GROUP_BUCKET_FORMAT =
-            "       id=0x%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
-
-    private static final String CONTROLLER = "CONTROLLER";
-
-    @Option(name = "-v", aliases = "--verbose", description = "Outputs complete path")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity1 = false;
-
-    @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs flows and groups for every device")
-    @Completion(PlaceholderCompleter.class)
-    private boolean verbosity2 = false;
-
-    @Option(name = "-s", aliases = "--srcIp", description = "Source IP")
-    @Completion(PlaceholderCompleter.class)
-    String srcIp = null;
-
-    @Option(name = "-sp", aliases = "--srcPort", description = "Source Port", required = true)
-    @Completion(ConnectPointCompleter.class)
-    String srcPort = null;
-
-    @Option(name = "-sm", aliases = "--srcMac", description = "Source MAC")
-    @Completion(PlaceholderCompleter.class)
-    String srcMac = null;
-
-    @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
-    @Completion(EthTypeCompleter.class)
-    String ethType = "ipv4";
-
-    @Option(name = "-stp", aliases = "--srcTcpPort", description = "Source TCP Port")
-    @Completion(PlaceholderCompleter.class)
-    String srcTcpPort = null;
-
-    @Option(name = "-d", aliases = "--dstIp", description = "Destination IP")
-    @Completion(PlaceholderCompleter.class)
-    String dstIp = null;
-
-    @Option(name = "-dm", aliases = "--dstMac", description = "Destination MAC")
-    @Completion(PlaceholderCompleter.class)
-    String dstMac = null;
-
-    @Option(name = "-dtp", aliases = "--dstTcpPort", description = "destination TCP Port")
-    @Completion(PlaceholderCompleter.class)
-    String dstTcpPort = null;
-
-    @Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
-    @Completion(PlaceholderCompleter.class)
-    String vlan = "None";
-
-    @Option(name = "-ml", aliases = "--mplsLabel", description = "Mpls label of incoming packet")
-    @Completion(PlaceholderCompleter.class)
-    String mplsLabel = null;
-
-    @Option(name = "-mb", aliases = "--mplsBos", description = "MPLS BOS")
-    @Completion(PlaceholderCompleter.class)
-    String mplsBos = null;
-
-    @Option(name = "-ipp", aliases = "--ipProto", description = "IP Proto")
-    @Completion(IpProtocolCompleter.class)
-    String ipProto = null;
-
-    @Option(name = "-udps", aliases = "--udpSrc", description = "UDP Source")
-    @Completion(PlaceholderCompleter.class)
-    String udpSrc = null;
-
-    @Option(name = "-udpd", aliases = "--udpDst", description = "UDP Destination")
-    @Completion(PlaceholderCompleter.class)
-    String udpDst = null;
-
-    @Override
-    protected void doExecute() {
-        TroubleshootService service = get(TroubleshootService.class);
-        if (!service.checkNibValidity()) {
-            // if the NIB is found invalid, fill it with the current network states so that this command can proceed
-            print(T3CliUtils.NIB_AUTOFILLED);
-            TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
-            cmd.doExecute();
-            if (!service.checkNibValidity()) {
-                // if the NIB is still invalid even after auto-filled snapshots, stop and warn
-                print(T3CliUtils.NIB_TERMINATE);
-                return;
-            }
-        } else {
-            print(service.printNibSummary());
-        }
-
-        String[] cpInfo = srcPort.split("/");
-        Preconditions.checkArgument(cpInfo.length == 2, "wrong format of source port");
-        ConnectPoint cp;
-        //Uses input port as a convenience to carry the Controller port, proper flood behaviour is handled in the
-        // troubleshoot manager.
-        if (cpInfo[1].equalsIgnoreCase(CONTROLLER)) {
-            cp = new ConnectPoint(DeviceId.deviceId(cpInfo[0]), PortNumber.CONTROLLER);
-        } else {
-            cp = ConnectPoint.deviceConnectPoint(srcPort);
-        }
-
-        EtherType type = EtherType.valueOf(ethType.toUpperCase());
-
-        //Input Port must be specified
-        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder()
-                .matchInPort(cp.port());
-
-        if (srcIp != null) {
-            if (type.equals(EtherType.IPV6)) {
-                selectorBuilder.matchIPv6Src(IpAddress.valueOf(srcIp).toIpPrefix());
-            } else {
-                selectorBuilder.matchIPSrc(IpAddress.valueOf(srcIp).toIpPrefix());
-            }
-        }
-
-        if (srcMac != null) {
-            selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMac));
-        }
-
-        //if EthType option is not specified using IPv4
-        selectorBuilder.matchEthType(type.ethType().toShort());
-
-        if (srcTcpPort != null) {
-            selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpPort)));
-        }
-
-        if (dstIp != null) {
-            if (type.equals(EtherType.IPV6)) {
-                selectorBuilder.matchIPv6Dst(IpAddress.valueOf(dstIp).toIpPrefix());
-            } else {
-                selectorBuilder.matchIPDst(IpAddress.valueOf(dstIp).toIpPrefix());
-            }
-        }
-
-        if (dstMac != null) {
-            selectorBuilder.matchEthDst(MacAddress.valueOf(dstMac));
-        }
-        if (dstTcpPort != null) {
-            selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpPort)));
-        }
-
-        //if vlan option is not specified using NONE
-        selectorBuilder.matchVlanId(VlanId.vlanId(vlan));
-
-        if (mplsLabel != null) {
-            selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(Integer.parseInt(mplsLabel)));
-        }
-
-        if (mplsBos != null) {
-            selectorBuilder.matchMplsBos(Boolean.valueOf(mplsBos));
-        }
-
-        if (ipProto != null) {
-            selectorBuilder.matchIPProtocol(Byte.valueOf(ipProto));
-        }
-
-        if (udpSrc != null) {
-            selectorBuilder.matchUdpSrc(TpPort.tpPort(Integer.parseInt(udpSrc)));
-        }
-
-        if (udpDst != null) {
-            selectorBuilder.matchUdpDst(TpPort.tpPort(Integer.parseInt(udpDst)));
-        }
-
-
-        TrafficSelector packet = selectorBuilder.build();
-
-        //Printing the created packet
-        print("Tracing packet: %s", packet.criteria());
-
-        //Build the trace
-        StaticPacketTrace trace = service.trace(packet, cp);
-
-        print("%s", T3CliUtils.printTrace(trace, verbosity1, verbosity2));
-
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/package-info.java
deleted file mode 100644
index b956df2..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-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.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics CLI.
- */
-package org.onosproject.t3.cli;
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Generator.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/Generator.java
deleted file mode 100644
index 82ad628..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Generator.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2018-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.t3.impl;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Generator class that yields instances of T type objects as soon as they are ready.
- *
- * @param <T> type of the object.
- */
-public abstract class Generator<T> implements Iterable<T> {
-
-    private class Condition {
-        private boolean isSet;
-
-        synchronized void set() {
-            isSet = true;
-            notifyAll();
-        }
-
-        synchronized void await() throws InterruptedException {
-            try {
-
-                if (isSet) {
-                    return;
-                }
-
-                while (!isSet) {
-                    wait();
-                }
-            } finally {
-                isSet = false;
-            }
-        }
-    }
-
-    private static ThreadGroup threadGroup;
-
-    private Thread producer;
-    private boolean hasFinished;
-    private final Condition itemAvailableOrHasFinished = new Condition();
-    private final Condition itemRequested = new Condition();
-    private T nextItem;
-    private boolean nextItemAvailable;
-    private RuntimeException exceptionRaisedByProducer;
-
-    @Override
-    public Iterator<T> iterator() {
-        return new Iterator<T>() {
-            @Override
-            public boolean hasNext() {
-                return waitForNext();
-            }
-
-            @Override
-            public T next() {
-                if (!waitForNext()) {
-                    throw new NoSuchElementException();
-                }
-                nextItemAvailable = false;
-                return nextItem;
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-
-            private boolean waitForNext() {
-                if (nextItemAvailable) {
-                    return true;
-                }
-                if (hasFinished) {
-                    return false;
-                }
-                if (producer == null) {
-                    startProducer();
-                }
-                itemRequested.set();
-                try {
-                    itemAvailableOrHasFinished.await();
-                } catch (InterruptedException e) {
-                    hasFinished = true;
-                    producer.interrupt();
-                    try {
-                        producer.join();
-                    } catch (InterruptedException e1) {
-                        // Interrupting the broken thread
-                        Thread.currentThread().interrupt();
-                        throw new IllegalStateException(e1);
-                    }
-                }
-                if (exceptionRaisedByProducer != null) {
-                    throw exceptionRaisedByProducer;
-                }
-                return !hasFinished;
-            }
-        };
-    }
-
-    protected abstract void run() throws InterruptedException;
-
-    void yield(T element) throws InterruptedException {
-        nextItem = element;
-        nextItemAvailable = true;
-        itemAvailableOrHasFinished.set();
-        itemRequested.await();
-    }
-
-    private void startProducer() {
-        assert producer == null;
-        synchronized (this) {
-            if (threadGroup == null) {
-                threadGroup = new ThreadGroup("onos-t3-generator");
-            }
-        }
-        producer = new Thread(threadGroup, () -> {
-            try {
-                itemRequested.await();
-                Generator.this.run();
-            } catch (InterruptedException e) {
-                // Remaining steps in run() will shut down thread.
-            } catch (RuntimeException e) {
-                exceptionRaisedByProducer = e;
-            }
-            hasFinished = true;
-            itemAvailableOrHasFinished.set();
-        });
-        producer.setDaemon(true);
-        producer.start();
-    }
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/McastGenerator.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/McastGenerator.java
deleted file mode 100644
index 7520843..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/McastGenerator.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2018-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.t3.impl;
-
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.slf4j.Logger;
-
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Implementation of the generator class that yields a set of Packet Traces.
- */
-public class McastGenerator extends Generator<Set<StaticPacketTrace>> {
-
-    private static final Logger log = getLogger(McastGenerator.class);
-    protected static final MacAddress IPV4_ADDRESS = MacAddress.valueOf("01:00:5E:00:00:00");
-    protected static final MacAddress IPV6_ADDRESS = MacAddress.valueOf("33:33:00:00:00:00");
-    private static final String NO_SINK = "There is no sink for this mcast route";
-    private static final String GENERATOR_ERROR =
-            "Generator for mcast route trace has benn interrupted. The trace result may be incomplete.";
-
-    private final MulticastRouteNib mcastRouteNib;
-    private final TroubleshootManager manager;
-    private final VlanId vlanId;
-
-    /**
-     * Creates a generator for obtaining traces of all configured multicast routes.
-     *
-     * @param mcastRouteNib the multicast route NIB
-     * @param manager the troubleshoot manager issuing the request.
-     * @param vlanId  the multicast configured VlanId.
-     */
-    McastGenerator(MulticastRouteNib mcastRouteNib, TroubleshootManager manager, VlanId vlanId) {
-        this.mcastRouteNib = mcastRouteNib;
-        this.manager = manager;
-        this.vlanId = vlanId;
-    }
-
-    @Override
-    protected void run() {
-        mcastRouteNib.getRoutes().forEach(route -> {
-            McastRouteData routeData = mcastRouteNib.routeData(route);
-            IpAddress group = route.group();
-            routeData.sources().forEach((host, sources) -> {
-                sources.forEach(source -> {
-                    TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
-                            .matchVlanId(vlanId)
-                            .matchInPort(source.port());
-                    if (group.isIp4()) {
-                        selector.matchEthDst(IPV4_ADDRESS)
-                                .matchIPDst(group.toIpPrefix())
-                                .matchEthType(EthType.EtherType.IPV4.ethType().toShort());
-                    } else {
-                        selector.matchEthDst(IPV6_ADDRESS)
-                                .matchIPv6Dst(group.toIpPrefix())
-                                .matchEthType(EthType.EtherType.IPV6.ethType().toShort());
-                    }
-
-                    StaticPacketTrace trace;
-                    // check this mcast route has no sink
-                    if (routeData.allSinks().size() == 0) {
-                        trace = new StaticPacketTrace(selector.build(), source);
-                        trace.addResultMessage(NO_SINK);
-                        // tracing mcast route with no sink is not a failure
-                        trace.setSuccess(true);
-                    } else {
-                        trace = manager.trace(selector.build(), source);
-                    }
-                    try {
-                        yield(ImmutableSet.of(trace));
-                    } catch (InterruptedException e) {
-                        log.warn("Interrupted generator", e.getMessage());
-                        log.debug("exception", e);
-                        trace.setSuccess(false);
-                        trace.addResultMessage(GENERATOR_ERROR);
-                    }
-                });
-            });
-        });
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/PingAllGenerator.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/PingAllGenerator.java
deleted file mode 100644
index e935fad..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/PingAllGenerator.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2018-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.t3.impl;
-
-import com.google.common.collect.Sets;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.slf4j.Logger;
-
-import java.util.List;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Implementation of the generator class that yields a set of Packet Traces.
- */
-public class PingAllGenerator extends Generator<Set<StaticPacketTrace>> {
-
-    private static final Logger log = getLogger(PingAllGenerator.class);
-
-    private final EthType.EtherType etherType;
-    private final HostNib hostNib;
-    private final TroubleshootManager manager;
-
-    /**
-     * Creates a generator for obtaining traces of pings between all the hosts in the network.
-     *
-     * @param etherType the type of traffic we are tracing.
-     * @param hostNib   the host NIB
-     * @param manager   the troubleshoot manager issuing the request.
-     */
-    PingAllGenerator(EthType.EtherType etherType, HostNib hostNib, TroubleshootManager manager) {
-        this.etherType = etherType;
-        this.hostNib = hostNib;
-        this.manager = manager;
-    }
-
-    @Override
-    protected void run() throws InterruptedException {
-        hostNib.getHosts().forEach(host -> {
-            List<IpAddress> ipAddresses = manager.getIpAddresses(host, etherType, false);
-            if (ipAddresses.size() > 0) {
-                //check if the host has only local IPs of that ETH type
-                boolean onlyLocalSrc = ipAddresses.size() == 1 && ipAddresses.get(0).isLinkLocal();
-                hostNib.getHosts().forEach(hostToPing -> {
-                    List<IpAddress> ipAddressesToPing = manager.getIpAddresses(hostToPing, etherType, false);
-                    //check if the other host has only local IPs of that ETH type
-                    boolean onlyLocalDst = ipAddressesToPing.size() == 1 && ipAddressesToPing.get(0).isLinkLocal();
-                    boolean sameLocation = Sets.intersection(host.locations(), hostToPing.locations()).size() > 0;
-                    //Trace is done only if they are both local and under the same location
-                    // or not local and if they are not the same host.
-                    if (((sameLocation && onlyLocalDst && onlyLocalSrc) ||
-                            (!onlyLocalSrc && !onlyLocalDst && ipAddressesToPing.size() > 0))
-                            && !host.equals(hostToPing)) {
-                        try {
-                            yield(manager.trace(host.id(), hostToPing.id(), etherType));
-                        } catch (InterruptedException e) {
-                            log.warn("Interrupted generator", e.getMessage());
-                            log.debug("exception", e);
-                        }
-                    }
-                });
-            }
-        });
-
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Subnet.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/Subnet.java
deleted file mode 100644
index ac5a741..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Subnet.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2017-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.t3.impl;
-
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * Utility class to test if an Ip is in a given subnet.
- */
-public class Subnet {
-    private final int bytesSubnetCount;
-    private final BigInteger bigMask;
-    private final BigInteger bigSubnetMasked;
-
-    /**
-     * Constructor for use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57".
-     * @param subnetAddress the address
-     * @param bits the mask
-     */
-    public Subnet(InetAddress subnetAddress, int bits) {
-        bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
-        bigMask = BigInteger.valueOf(-1).shiftLeft(bytesSubnetCount * 8 - bits); // mask = -1 << 32 - bits
-        bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(bigMask);
-    }
-
-    /**
-     * Constructor for use via format "192.168.0.0/255.255.255.0" or single address.
-     * @param subnetAddress the address
-     * @param mask the mask
-     */
-    public Subnet(InetAddress subnetAddress, InetAddress mask) {
-        bytesSubnetCount = subnetAddress.getAddress().length;
-        // no mask given case is handled here.
-        bigMask = null == mask ? BigInteger.valueOf(-1) : new BigInteger(mask.getAddress());
-        bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(bigMask);
-    }
-
-    /**
-     * Subnet factory method.
-     *
-     * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
-     *                   or single address or "2001:db8:85a3:880:0:0:0:0/57"
-     * @return a new instance
-     * @throws UnknownHostException thrown if unsupported subnet mask.
-     */
-    public static Subnet createInstance(String subnetMask)
-            throws UnknownHostException {
-        final String[] stringArr = subnetMask.split("/");
-        if (2 > stringArr.length) {
-            return new Subnet(InetAddress.getByName(stringArr[0]), (InetAddress) null);
-        } else if (stringArr[1].contains(".") || stringArr[1].contains(":")) {
-            return new Subnet(InetAddress.getByName(stringArr[0]), InetAddress.getByName(stringArr[1]));
-        } else {
-            return new Subnet(InetAddress.getByName(stringArr[0]), Integer.parseInt(stringArr[1]));
-        }
-    }
-
-    /**
-     * Tests if the address is in the given subnet.
-     * @param address the address to test.
-     * @return true if inside the subnet
-     */
-    public boolean isInSubnet(InetAddress address) {
-        byte[] bytesAddress = address.getAddress();
-        if (this.bytesSubnetCount != bytesAddress.length) {
-            return false;
-        }
-        BigInteger bigAddress = new BigInteger(bytesAddress);
-        return bigAddress.and(this.bigMask).equals(this.bigSubnetMasked);
-    }
-
-    @Override
-    public final boolean equals(Object obj) {
-        if (!(obj instanceof Subnet)) {
-            return false;
-        }
-        final Subnet other = (Subnet) obj;
-        return bigSubnetMasked.equals(other.bigSubnetMasked) &&
-                bigMask.equals(other.bigMask) &&
-                bytesSubnetCount == other.bytesSubnetCount;
-    }
-
-    @Override
-    public final int hashCode() {
-        return bytesSubnetCount;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder buf = new StringBuilder();
-        bigInteger2IpString(buf, bigSubnetMasked, bytesSubnetCount);
-        buf.append('/');
-        bigInteger2IpString(buf, bigMask, bytesSubnetCount);
-        return buf.toString();
-    }
-
-    private void bigInteger2IpString(StringBuilder buf, BigInteger bigInteger, int displayBytes) {
-        boolean isIPv4 = 4 == displayBytes;
-        byte[] bytes = bigInteger.toByteArray();
-        int diffLen = displayBytes - bytes.length;
-        byte fillByte = 0 > (int) bytes[0] ? (byte) 0xFF : (byte) 0x00;
-
-        int integer;
-        for (int i = 0; i < displayBytes; i++) {
-            if (0 < i && !isIPv4 && i % 2 == 0) {
-                buf.append(':');
-            } else if (0 < i && isIPv4) {
-                buf.append('.');
-            }
-            integer = 0xFF & (i < diffLen ? fillByte : bytes[i - diffLen]);
-            if (!isIPv4 && 0x10 > integer) {
-                buf.append('0');
-            }
-            buf.append(isIPv4 ? integer : Integer.toHexString(integer));
-        }
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
deleted file mode 100644
index bc04136..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*
- * Copyright 2017-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.t3.impl;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.ConfigException;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.IndexTableId;
-import org.onosproject.net.flow.TableId;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.GroupsInDevice;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.NetworkConfigNib;
-import org.onosproject.t3.api.NibProfile;
-import org.onosproject.t3.api.RouteNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.osgi.service.component.annotations.Component;
-import org.slf4j.Logger;
-
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import static org.onlab.packet.EthType.EtherType;
-import static org.onosproject.net.flow.TrafficSelector.Builder;
-import static org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
-import static org.onosproject.t3.impl.TroubleshootUtils.compareMac;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Manager to troubleshoot packets inside the network.
- * Given a representation of a packet follows it's path in the network according to the existing flows and groups in
- * the devices.
- */
-@Component(immediate = true, service = TroubleshootService.class)
-public class TroubleshootManager implements TroubleshootService {
-
-    private static final Logger log = getLogger(TroubleshootManager.class);
-
-    static final String PACKET_TO_CONTROLLER = "Packet goes to the controller";
-
-    // uses a snapshot (cache) of NIBs instead of interacting with ONOS core in runtime
-    protected FlowNib flowNib = FlowNib.getInstance();
-    protected GroupNib groupNib = GroupNib.getInstance();
-    protected LinkNib linkNib = LinkNib.getInstance();
-    protected HostNib hostNib = HostNib.getInstance();
-    protected DeviceNib deviceNib = DeviceNib.getInstance();
-    protected DriverNib driverNib = DriverNib.getInstance();
-    protected MastershipNib mastershipNib = MastershipNib.getInstance();
-    protected EdgePortNib edgePortNib = EdgePortNib.getInstance();
-    protected RouteNib routeNib = RouteNib.getInstance();
-    protected NetworkConfigNib networkConfigNib = NetworkConfigNib.getInstance();
-    protected MulticastRouteNib mcastRouteNib = MulticastRouteNib.getInstance();
-
-    @Override
-    public boolean checkNibValidity() {
-        return Stream.of(flowNib, groupNib, linkNib, hostNib, deviceNib, driverNib,
-                mastershipNib, edgePortNib, routeNib, networkConfigNib, mcastRouteNib)
-                .allMatch(nib -> nib != null && nib.isValid());
-    }
-
-    @Override
-    public String printNibSummary() {
-        StringBuilder summary = new StringBuilder().append("*** Current NIB in valid: ***\n");
-        Stream.of(flowNib, groupNib, linkNib, hostNib, deviceNib, driverNib,
-                mastershipNib, edgePortNib, routeNib, networkConfigNib, mcastRouteNib)
-                .forEach(nib -> {
-                    NibProfile profile = nib.getProfile();
-                    summary.append(String.format(
-                            nib.getClass().getName() + " created %s from %s\n",
-                            profile.date(), profile.sourceType()));
-                });
-
-        return summary.append(StringUtils.rightPad("", 125, '-')).toString();
-    }
-
-    @Override
-    public List<StaticPacketTrace> pingAll(EtherType type) {
-        ImmutableList.Builder<StaticPacketTrace> tracesBuilder = ImmutableList.builder();
-        hostNib.getHosts().forEach(host -> {
-            List<IpAddress> ipAddresses = getIpAddresses(host, type, false);
-            if (ipAddresses.size() > 0) {
-                //check if the host has only local IPs of that ETH type
-                boolean onlyLocalSrc = ipAddresses.size() == 1 && ipAddresses.get(0).isLinkLocal();
-                hostNib.getHosts().forEach(hostToPing -> {
-                    List<IpAddress> ipAddressesToPing = getIpAddresses(hostToPing, type, false);
-                    //check if the other host has only local IPs of that ETH type
-                    boolean onlyLocalDst = ipAddressesToPing.size() == 1 && ipAddressesToPing.get(0).isLinkLocal();
-                    boolean sameLocation = Sets.intersection(host.locations(), hostToPing.locations()).size() > 0;
-                    //Trace is done only if they are both local and under the same location
-                    // or not local and if they are not the same host.
-                    if (((sameLocation && onlyLocalDst && onlyLocalSrc) ||
-                            (!onlyLocalSrc && !onlyLocalDst && ipAddressesToPing.size() > 0))
-                            && !host.equals(hostToPing)) {
-                        tracesBuilder.addAll(trace(host.id(), hostToPing.id(), type));
-                    }
-                });
-            }
-        });
-        return tracesBuilder.build();
-    }
-
-    @Override
-    public Generator<Set<StaticPacketTrace>> pingAllGenerator(EtherType type) {
-        return new PingAllGenerator(type, hostNib, this);
-    }
-
-    @Override
-    public Generator<Set<StaticPacketTrace>> traceMcast(VlanId vlanId) {
-        return new McastGenerator(mcastRouteNib, this, vlanId);
-    }
-
-    @Override
-    public Set<StaticPacketTrace> trace(HostId sourceHost, HostId destinationHost, EtherType etherType) {
-        Host source = hostNib.getHost(sourceHost);
-        Host destination = hostNib.getHost(destinationHost);
-
-        //Temporary trace to fail in case we don't have enough information or what is provided is incoherent
-        StaticPacketTrace failTrace = new StaticPacketTrace(null, null, Pair.of(source, destination));
-
-        if (source == null) {
-            failTrace.addResultMessage("Source Host " + sourceHost + " does not exist");
-            failTrace.setSuccess(false);
-
-            return ImmutableSet.of(failTrace);
-        }
-
-        if (destination == null) {
-            failTrace.addResultMessage("Destination Host " + destinationHost + " does not exist");
-            failTrace.setSuccess(false);
-            return ImmutableSet.of(failTrace);
-        }
-
-        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder()
-                .matchEthType(etherType.ethType().toShort())
-                .matchEthDst(source.mac())
-                .matchVlanId(source.vlan());
-
-
-        try {
-            ImmutableSet.Builder<StaticPacketTrace> traces = ImmutableSet.builder();
-            //if the location deviceId is the same, the two hosts are under same subnet and vlan on the interface
-            // we are under same leaf so it's L2 Unicast.
-            if (areBridged(source, destination)) {
-                selectorBuilder.matchEthDst(destination.mac());
-                source.locations().forEach(hostLocation -> {
-                    selectorBuilder.matchInPort(hostLocation.port());
-                    StaticPacketTrace trace = trace(selectorBuilder.build(), hostLocation);
-                    trace.addEndpointHosts(Pair.of(source, destination));
-                    traces.add(trace);
-                });
-                //The destination host is not dual homed, if it is the other path might be done through routing.
-                if (destination.locations().size() == 1) {
-                    return traces.build();
-                }
-            }
-            //handle the IPs for src and dst in case of L3
-            if (etherType.equals(EtherType.IPV4) || etherType.equals(EtherType.IPV6)) {
-
-                //Match on the source IP
-                if (!matchIP(source, failTrace, selectorBuilder, etherType, true)) {
-                    return ImmutableSet.of(failTrace);
-                }
-
-                //Match on destination IP
-                if (!matchIP(destination, failTrace, selectorBuilder, etherType, false)) {
-                    return ImmutableSet.of(failTrace);
-                }
-
-            } else {
-                failTrace.addResultMessage("Host based trace supports only IPv4 or IPv6 as EtherType, " +
-                        "please use packet based");
-                failTrace.setSuccess(false);
-                return ImmutableSet.of(failTrace);
-            }
-
-            //l3 unicast, we get the dst mac of the leaf the source is connected to from netcfg
-            SegmentRoutingDeviceConfig segmentRoutingConfig = networkConfigNib.getConfig(source.location()
-                    .deviceId(), SegmentRoutingDeviceConfig.class);
-            if (segmentRoutingConfig != null) {
-                selectorBuilder.matchEthDst(segmentRoutingConfig.routerMac());
-            } else {
-                failTrace.addResultMessage("Can't get " + source.location().deviceId() +
-                        " router MAC from segment routing config can't perform L3 tracing.");
-                failTrace.setSuccess(false);
-            }
-            source.locations().forEach(hostLocation -> {
-                selectorBuilder.matchInPort(hostLocation.port());
-                StaticPacketTrace trace = trace(selectorBuilder.build(), hostLocation);
-                trace.addEndpointHosts(Pair.of(source, destination));
-                traces.add(trace);
-            });
-            return traces.build();
-
-        } catch (ConfigException e) {
-            failTrace.addResultMessage("Can't get config " + e.getMessage());
-            return ImmutableSet.of(failTrace);
-        }
-    }
-
-    /**
-     * Matches src and dst IPs based on host information.
-     *
-     * @param host            the host
-     * @param failTrace       the trace to use in case of failure
-     * @param selectorBuilder the packet we are building to trace
-     * @param etherType       the traffic type
-     * @param src             is this src host or dst host
-     * @return true if properly matched
-     */
-    private boolean matchIP(Host host, StaticPacketTrace failTrace, Builder selectorBuilder,
-                            EtherType etherType, boolean src) {
-        List<IpAddress> ips = getIpAddresses(host, etherType, true);
-
-        if (ips.size() > 0) {
-            if (etherType.equals(EtherType.IPV4)) {
-                if (src) {
-                    selectorBuilder.matchIPSrc(ips.get(0).toIpPrefix());
-                } else {
-                    selectorBuilder.matchIPDst(ips.get(0).toIpPrefix());
-                }
-            } else if (etherType.equals(EtherType.IPV6)) {
-                if (src) {
-                    selectorBuilder.matchIPv6Src(ips.get(0).toIpPrefix());
-                } else {
-                    selectorBuilder.matchIPv6Dst(ips.get(0).toIpPrefix());
-                }
-            }
-        } else {
-            failTrace.addResultMessage("Host " + host + " has no " + etherType + " address");
-            failTrace.setSuccess(false);
-            return false;
-        }
-        return true;
-    }
-
-    List<IpAddress> getIpAddresses(Host host, EtherType etherType, boolean checklocal) {
-        return host.ipAddresses().stream().filter(ipAddress -> {
-            boolean correctIp = false;
-            if (etherType.equals(EtherType.IPV4)) {
-                correctIp = ipAddress.isIp4();
-            } else if (etherType.equals(EtherType.IPV6)) {
-                correctIp = ipAddress.isIp6();
-            }
-            if (checklocal) {
-                correctIp = correctIp && !ipAddress.isLinkLocal();
-            }
-            return correctIp;
-        }).collect(Collectors.toList());
-    }
-
-    /**
-     * Checks that two hosts are bridged (L2Unicast).
-     *
-     * @param source      the source host
-     * @param destination the destination host
-     * @return true if bridged.
-     * @throws ConfigException if config can't be properly retrieved
-     */
-    private boolean areBridged(Host source, Host destination) throws ConfigException {
-
-        //If the locations is not the same we don't even check vlan or subnets
-        if (Collections.disjoint(source.locations(), destination.locations())) {
-            return false;
-        }
-
-        if (!source.vlan().equals(VlanId.NONE) && !destination.vlan().equals(VlanId.NONE)
-                && !source.vlan().equals(destination.vlan())) {
-            return false;
-        }
-
-        InterfaceConfig interfaceCfgH1 = networkConfigNib.getConfig(source.location(), InterfaceConfig.class);
-        InterfaceConfig interfaceCfgH2 = networkConfigNib.getConfig(destination.location(), InterfaceConfig.class);
-        if (interfaceCfgH1 != null && interfaceCfgH2 != null) {
-
-            //following can be optimized but for clarity is left as is
-            Interface intfH1 = interfaceCfgH1.getInterfaces().stream().findFirst().get();
-            Interface intfH2 = interfaceCfgH2.getInterfaces().stream().findFirst().get();
-
-            if (source.vlan().equals(VlanId.NONE) && !destination.vlan().equals(VlanId.NONE)) {
-                return intfH1.vlanUntagged().equals(destination.vlan()) ||
-                        intfH1.vlanNative().equals(destination.vlan());
-            }
-
-            if (!source.vlan().equals(VlanId.NONE) && destination.vlan().equals(VlanId.NONE)) {
-                return intfH2.vlanUntagged().equals(source.vlan()) ||
-                        intfH2.vlanNative().equals(source.vlan());
-            }
-
-            if (!intfH1.vlanNative().equals(intfH2.vlanNative())) {
-                return false;
-            }
-
-            if (!intfH1.vlanUntagged().equals(intfH2.vlanUntagged())) {
-                return false;
-            }
-
-            List<InterfaceIpAddress> intersection = new ArrayList<>(intfH1.ipAddressesList());
-            intersection.retainAll(intfH2.ipAddressesList());
-            if (intersection.size() == 0) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public StaticPacketTrace trace(TrafficSelector packet, ConnectPoint in) {
-        log.info("Tracing packet {} coming in through {}", packet, in);
-        //device must exist in ONOS
-        Preconditions.checkNotNull(deviceNib.getDevice(in.deviceId()),
-                "Device " + in.deviceId() + " must exist in ONOS");
-
-        StaticPacketTrace trace = new StaticPacketTrace(packet, in);
-        boolean isDualHomed = getHosts(trace).stream().anyMatch(host -> host.locations().size() > 1);
-        //FIXME this can be done recursively
-        //Building output connect Points
-        List<ConnectPoint> path = new ArrayList<>();
-        trace = traceInDevice(trace, packet, in, isDualHomed, path);
-        trace = getTrace(path, in, trace, isDualHomed);
-        return trace;
-    }
-
-    @Override
-    public List<Set<StaticPacketTrace>> getMulitcastTrace(VlanId vlanId) {
-        Generator<Set<StaticPacketTrace>> gen = new McastGenerator(mcastRouteNib, this, vlanId);
-        List<Set<StaticPacketTrace>> multicastTraceList =
-                StreamSupport.stream(gen.spliterator(), false).collect(Collectors.toList());
-        return multicastTraceList;
-    }
-
-    /**
-     * Computes a trace for a give packet that start in the network at the given connect point.
-     *
-     * @param completePath the path traversed by the packet
-     * @param in           the input connect point
-     * @param trace        the trace to build
-     * @param isDualHomed  true if the trace we are doing starts or ends in a dual homed host
-     * @return the build trace for that packet.
-     */
-    private StaticPacketTrace getTrace(List<ConnectPoint> completePath, ConnectPoint in, StaticPacketTrace trace,
-                                       boolean isDualHomed) {
-
-        log.debug("------------------------------------------------------------");
-
-        //if the trace already contains the input connect point there is a loop
-        if (pathContainsDevice(completePath, in.deviceId())) {
-            trace.addResultMessage("Loop encountered in device " + in.deviceId());
-            completePath.add(in);
-            trace.addCompletePath(completePath);
-            trace.setSuccess(false);
-            return trace;
-        }
-
-        //let's add the input connect point
-        completePath.add(in);
-
-        //If the trace has no outputs for the given input we stop here
-        if (trace.getGroupOuputs(in.deviceId()) == null) {
-            computePath(completePath, trace, null);
-            trace.addResultMessage("No output out of device " + in.deviceId() + ". Packet is dropped");
-            trace.setSuccess(false);
-            return trace;
-        }
-
-        //If the trace has outputs we analyze them all
-        for (GroupsInDevice outputPath : trace.getGroupOuputs(in.deviceId())) {
-
-            ConnectPoint cp = outputPath.getOutput();
-            log.debug("Connect point in {}", in);
-            log.debug("Output path {}", cp);
-            log.debug("{}", outputPath.getFinalPacket());
-
-            //Hosts for the the given output
-            Set<Host> hostsList = hostNib.getConnectedHosts(cp);
-            //Hosts queried from the original ip or mac
-            Set<Host> hosts = getHosts(trace);
-
-            if (in.equals(cp) && trace.getInitialPacket().getCriterion(Criterion.Type.VLAN_VID) != null &&
-                    outputPath.getFinalPacket().getCriterion(Criterion.Type.VLAN_VID) != null
-                    && ((VlanIdCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.VLAN_VID)).vlanId()
-                    .equals(((VlanIdCriterion) outputPath.getFinalPacket().getCriterion(Criterion.Type.VLAN_VID))
-                            .vlanId())) {
-                if (trace.getGroupOuputs(in.deviceId()).size() == 1 &&
-                        computePath(completePath, trace, outputPath.getOutput())) {
-                    trace.addResultMessage("Connect point out " + cp + " is same as initial input " + in);
-                    trace.setSuccess(false);
-                }
-            } else if (!Collections.disjoint(hostsList, hosts)) {
-                //If the two host collections contain the same item it means we reached the proper output
-                log.debug("Stopping here because host is expected destination {}, reached through", completePath);
-                if (computePath(completePath, trace, outputPath.getOutput())) {
-                    trace.addResultMessage("Reached required destination Host " + cp);
-                    trace.setSuccess(true);
-                }
-                break;
-            } else if (cp.port().equals(PortNumber.CONTROLLER)) {
-
-                //Getting the master when the packet gets sent as packet in
-                NodeId master = mastershipNib.getMasterFor(cp.deviceId());
-                // TODO if we don't need to print master node id, exclude mastership NIB which is used only here
-                trace.addResultMessage(PACKET_TO_CONTROLLER + " " + master.id());
-                computePath(completePath, trace, outputPath.getOutput());
-                handleVlanToController(outputPath, trace);
-
-            } else if (linkNib.getEgressLinks(cp).size() > 0) {
-
-                //TODO this can be optimized if we use a Tree structure for paths.
-                //if we already have outputs let's check if the one we are considering starts from one of the devices
-                // in any of the ones we have.
-                if (trace.getCompletePaths().size() > 0) {
-                    ConnectPoint inputForOutput = null;
-                    List<ConnectPoint> previousPath = new ArrayList<>();
-                    for (List<ConnectPoint> path : trace.getCompletePaths()) {
-                        for (ConnectPoint connect : path) {
-                            //if the path already contains the input for the output we've found we use it
-                            if (connect.equals(in)) {
-                                inputForOutput = connect;
-                                previousPath = path;
-                                break;
-                            }
-                        }
-                    }
-
-                    //we use the pre-existing path up to the point we fork to a new output
-                    if (inputForOutput != null && completePath.contains(inputForOutput)) {
-                        List<ConnectPoint> temp = new ArrayList<>(previousPath);
-                        temp = temp.subList(0, previousPath.indexOf(inputForOutput) + 1);
-                        if (completePath.containsAll(temp)) {
-                            completePath = temp;
-                        }
-                    }
-                }
-
-                //let's add the ouput for the input
-                completePath.add(cp);
-                //let's compute the links for the given output
-                Set<Link> links = linkNib.getEgressLinks(cp);
-                log.debug("Egress Links {}", links);
-                //For each link we trace the corresponding device
-                for (Link link : links) {
-                    ConnectPoint dst = link.dst();
-                    //change in-port to the dst link in port
-                    Builder updatedPacket = DefaultTrafficSelector.builder();
-                    outputPath.getFinalPacket().criteria().forEach(updatedPacket::add);
-                    updatedPacket.add(Criteria.matchInPort(dst.port()));
-                    log.debug("DST Connect Point {}", dst);
-                    //build the elements for that device
-                    traceInDevice(trace, updatedPacket.build(), dst, isDualHomed, completePath);
-                    //continue the trace along the path
-                    getTrace(completePath, dst, trace, isDualHomed);
-                }
-            } else if (edgePortNib.isEdgePoint(outputPath.getOutput()) &&
-                    trace.getInitialPacket().getCriterion(Criterion.Type.ETH_DST) != null &&
-                    ((EthCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.ETH_DST))
-                            .mac().isMulticast()) {
-                trace.addResultMessage("Packet is multicast and reached output " + outputPath.getOutput() +
-                        " which is enabled and is edge port");
-                trace.setSuccess(true);
-                computePath(completePath, trace, outputPath.getOutput());
-                if (!hasOtherOutput(in.deviceId(), trace, outputPath.getOutput())) {
-                    return trace;
-                }
-            } else if (deviceNib.getPort(cp) != null && deviceNib.getPort(cp).isEnabled()) {
-                EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) trace.getInitialPacket()
-                        .getCriterion(Criterion.Type.ETH_TYPE);
-                //We treat as correct output only if it's not LLDP or BDDP
-                if (!(ethTypeCriterion.ethType().equals(EtherType.LLDP.ethType())
-                        && !ethTypeCriterion.ethType().equals(EtherType.BDDP.ethType()))) {
-                    if (computePath(completePath, trace, outputPath.getOutput())) {
-                        if (hostsList.isEmpty()) {
-                            trace.addResultMessage("Packet is " + ((EthTypeCriterion) outputPath.getFinalPacket()
-                                    .getCriterion(Criterion.Type.ETH_TYPE)).ethType() + " and reached " +
-                                    cp + " with no hosts connected ");
-                        } else {
-                            IpAddress ipAddress = null;
-                            if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST) != null) {
-                                ipAddress = ((IPCriterion) trace.getInitialPacket()
-                                        .getCriterion(Criterion.Type.IPV4_DST)).ip().address();
-                            } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST) != null) {
-                                ipAddress = ((IPCriterion) trace.getInitialPacket()
-                                        .getCriterion(Criterion.Type.IPV6_DST)).ip().address();
-                            }
-                            if (ipAddress != null) {
-                                IpAddress finalIpAddress = ipAddress;
-                                if (hostsList.stream().anyMatch(host -> host.ipAddresses().contains(finalIpAddress)) ||
-                                        hostNib.getHostsByIp(finalIpAddress).isEmpty()) {
-                                    trace.addResultMessage("Packet is " +
-                                            ((EthTypeCriterion) outputPath.getFinalPacket()
-                                                    .getCriterion(Criterion.Type.ETH_TYPE)).ethType() +
-                                            " and reached " + cp + " with hosts " + hostsList);
-                                } else {
-                                    trace.addResultMessage("Wrong output " + cp + " for required destination ip " +
-                                            ipAddress);
-                                    trace.setSuccess(false);
-                                }
-                            } else {
-                                trace.addResultMessage("Packet is " + ((EthTypeCriterion) outputPath.getFinalPacket()
-                                        .getCriterion(Criterion.Type.ETH_TYPE)).ethType() + " and reached " +
-                                        cp + " with hosts " + hostsList);
-                            }
-                        }
-                        trace.setSuccess(true);
-                    }
-                }
-
-            } else {
-                computePath(completePath, trace, cp);
-                trace.setSuccess(false);
-                if (deviceNib.getPort(cp) == null) {
-                    //Port is not existent on device.
-                    log.warn("Port {} is not available on device.", cp);
-                    trace.addResultMessage("Port " + cp + "is not available on device. Packet is dropped");
-                } else {
-                    //No links means that the packet gets dropped.
-                    log.warn("No links out of {}", cp);
-                    trace.addResultMessage("No links depart from " + cp + ". Packet is dropped");
-                }
-            }
-        }
-        return trace;
-    }
-
-
-    /**
-     * If the initial packet comes tagged with a Vlan we output it with that to ONOS.
-     * If ONOS applied a vlan we remove it.
-     *
-     * @param outputPath the output
-     * @param trace      the trace we are building
-     */
-
-    private void handleVlanToController(GroupsInDevice outputPath, StaticPacketTrace trace) {
-
-        VlanIdCriterion initialVid = (VlanIdCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.VLAN_VID);
-        VlanIdCriterion finalVid = (VlanIdCriterion) outputPath.getFinalPacket().getCriterion(Criterion.Type.VLAN_VID);
-
-        if (initialVid != null && !initialVid.equals(finalVid) && initialVid.vlanId().equals(VlanId.NONE)) {
-
-            Set<Criterion> finalCriteria = new HashSet<>(outputPath.getFinalPacket().criteria());
-            //removing the final vlanId
-            finalCriteria.remove(finalVid);
-            Builder packetUpdated = DefaultTrafficSelector.builder();
-            finalCriteria.forEach(packetUpdated::add);
-            //Initial was none so we set it to that
-            packetUpdated.add(Criteria.matchVlanId(VlanId.NONE));
-            //Update final packet
-            outputPath.setFinalPacket(packetUpdated.build());
-        }
-    }
-
-    /**
-     * Checks if the device has other outputs than the given connect point.
-     *
-     * @param inDeviceId the device
-     * @param trace      the trace we are building
-     * @param cp         an output connect point
-     * @return true if the device has other outputs.
-     */
-    private boolean hasOtherOutput(DeviceId inDeviceId, StaticPacketTrace trace, ConnectPoint cp) {
-        return trace.getGroupOuputs(inDeviceId).stream().filter(groupsInDevice -> {
-            return !groupsInDevice.getOutput().equals(cp);
-        }).count() > 0;
-    }
-
-    /**
-     * Checks if the path contains the device.
-     *
-     * @param completePath the path
-     * @param deviceId     the device to check
-     * @return true if the path contains the device
-     */
-    //TODO might prove costly, improvement: a class with both CPs and DeviceIds point.
-    private boolean pathContainsDevice(List<ConnectPoint> completePath, DeviceId deviceId) {
-        for (ConnectPoint cp : completePath) {
-            if (cp.deviceId().equals(deviceId)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Gets the hosts for the given initial packet.
-     *
-     * @param trace the trace we are building
-     * @return set of the hosts we are trying to reach
-     */
-    private Set<Host> getHosts(StaticPacketTrace trace) {
-        IPCriterion ipv4Criterion = ((IPCriterion) trace.getInitialPacket()
-                .getCriterion(Criterion.Type.IPV4_DST));
-        IPCriterion ipv6Criterion = ((IPCriterion) trace.getInitialPacket()
-                .getCriterion(Criterion.Type.IPV6_DST));
-        Set<Host> hosts = new HashSet<>();
-        if (ipv4Criterion != null) {
-            hosts.addAll(hostNib.getHostsByIp(ipv4Criterion.ip().address()));
-        }
-        if (ipv6Criterion != null) {
-            hosts.addAll(hostNib.getHostsByIp(ipv6Criterion.ip().address()));
-        }
-        EthCriterion ethCriterion = ((EthCriterion) trace.getInitialPacket()
-                .getCriterion(Criterion.Type.ETH_DST));
-        if (ethCriterion != null) {
-            hosts.addAll(hostNib.getHostsByMac(ethCriterion.mac()));
-        }
-        return hosts;
-    }
-
-    /**
-     * Computes the list of traversed connect points.
-     *
-     * @param completePath the list of devices
-     * @param trace        the trace we are building
-     * @param output       the final output connect point
-     */
-    private boolean computePath(List<ConnectPoint> completePath, StaticPacketTrace trace, ConnectPoint output) {
-        List<ConnectPoint> traverseList = new ArrayList<>();
-        if (!completePath.contains(trace.getInitialConnectPoint())) {
-            traverseList.add(trace.getInitialConnectPoint());
-        }
-
-        if (output != null && trace.getInitialConnectPoint().deviceId().equals(output.deviceId())) {
-            trace.addCompletePath(ImmutableList.of(trace.getInitialConnectPoint(), output));
-            return true;
-        }
-
-        traverseList.addAll(completePath);
-        if (output != null && !completePath.contains(output)) {
-            traverseList.add(output);
-        }
-        if (!trace.getCompletePaths().contains(traverseList)) {
-            trace.addCompletePath(ImmutableList.copyOf(traverseList));
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Traces the packet inside a device starting from an input connect point.
-     *
-     * @param trace        the trace we are building
-     * @param packet       the packet we are tracing
-     * @param in           the input connect point.
-     * @param isDualHomed  true if the trace we are doing starts or ends in a dual homed host
-     * @param completePath the path up until this device
-     * @return updated trace
-     */
-    private StaticPacketTrace traceInDevice(StaticPacketTrace trace, TrafficSelector packet, ConnectPoint in,
-                                            boolean isDualHomed, List<ConnectPoint> completePath) {
-
-        boolean multipleRoutes = false;
-        if (trace.getGroupOuputs(in.deviceId()) != null) {
-            multipleRoutes = multipleRoutes(trace);
-        }
-        if (trace.getGroupOuputs(in.deviceId()) != null && !isDualHomed && !multipleRoutes) {
-            log.debug("Trace already contains device and given outputs");
-            return trace;
-        }
-
-        log.debug("Packet {} coming in from {}", packet, in);
-
-        //if device is not available exit here.
-        if (!deviceNib.isAvailable(in.deviceId())) {
-            trace.addResultMessage("Device is offline " + in.deviceId());
-            computePath(completePath, trace, null);
-            return trace;
-        }
-
-        //handle when the input is the controller
-        //NOTE, we are using the input port as a convenience to carry the CONTROLLER port number even if
-        // a packet in from the controller will not actually traverse the pipeline and have no such notion
-        // as the input port.
-        if (in.port().equals(PortNumber.CONTROLLER)) {
-            StaticPacketTrace outputTrace = inputFromController(trace, in);
-            if (outputTrace != null) {
-                return trace;
-            }
-        }
-
-        List<FlowEntry> flows = new ArrayList<>();
-        List<FlowEntry> outputFlows = new ArrayList<>();
-        List<Instruction> deferredInstructions = new ArrayList<>();
-
-        FlowEntry nextTableIdEntry = findNextTableIdEntry(in.deviceId(), -1);
-        if (nextTableIdEntry == null) {
-            trace.addResultMessage("No flow rules for device " + in.deviceId() + ". Aborting");
-            computePath(completePath, trace, null);
-            trace.setSuccess(false);
-            return trace;
-        }
-        TableId tableId = nextTableIdEntry.table();
-        FlowEntry flowEntry;
-        boolean output = false;
-        while (!output) {
-            log.debug("Searching a Flow Entry on table {} for packet {}", tableId, packet);
-            //get the rule that matches the incoming packet
-            flowEntry = matchHighestPriority(packet, in, tableId);
-            log.debug("Found Flow Entry {}", flowEntry);
-
-            boolean isOfdpaHardware = TroubleshootUtils.hardwareOfdpaMap
-                    .getOrDefault(driverNib.getDriverName(in.deviceId()), false);
-
-            //if the flow entry on a table is null and we are on hardware we treat as table miss, with few exceptions
-            if (flowEntry == null && isOfdpaHardware) {
-                log.debug("Ofdpa Hw setup, no flow rule means table miss");
-
-                if (((IndexTableId) tableId).id() == 27) {
-                    //Apparently a miss but Table 27 on OFDPA is a fixed table
-                    packet = handleOfdpa27FixedTable(trace, packet);
-                }
-
-                //Finding next table to go In case of miss
-                nextTableIdEntry = findNextTableIdEntry(in.deviceId(), ((IndexTableId) tableId).id());
-                log.debug("Next table id entry {}", nextTableIdEntry);
-
-                //FIXME find better solution that enable granularity greater than 0 or all rules
-                //(another possibility is max tableId)
-                if (nextTableIdEntry == null && flows.size() == 0) {
-                    trace.addResultMessage("No matching flow rules for device " + in.deviceId() + ". Aborting");
-                    computePath(completePath, trace, null);
-                    trace.setSuccess(false);
-                    return trace;
-
-                } else if (nextTableIdEntry == null) {
-                    //Means that no more flow rules are present
-                    output = true;
-
-                } else if (((IndexTableId) tableId).id() == 20) {
-                    //if the table is 20 OFDPA skips to table 50
-                    log.debug("A miss on Table 20 on OFDPA means that we skip directly to table 50");
-                    tableId = IndexTableId.of(50);
-
-                } else if (((IndexTableId) tableId).id() == 40) {
-                    //if the table is 40 OFDPA skips to table 60
-                    log.debug("A miss on Table 40 on OFDPA means that we skip directly to table 60");
-                    tableId = IndexTableId.of(60);
-                } else {
-                    tableId = nextTableIdEntry.table();
-                }
-
-            } else if (flowEntry == null) {
-                trace.addResultMessage("Packet has no match on table " + tableId + " in device " +
-                        in.deviceId() + ". Dropping");
-                computePath(completePath, trace, null);
-                trace.setSuccess(false);
-                return trace;
-            } else {
-
-                //IF the table has a transition
-                if (flowEntry.treatment().tableTransition() != null) {
-                    //update the next table we transitions to
-                    tableId = IndexTableId.of(flowEntry.treatment().tableTransition().tableId());
-                    log.debug("Flow Entry has transition to table Id {}", tableId);
-                    flows.add(flowEntry);
-                } else {
-                    //table has no transition so it means that it's an output rule if on the last table
-                    log.debug("Flow Entry has no transition to table, treating as last rule {}", flowEntry);
-                    flows.add(flowEntry);
-                    outputFlows.add(flowEntry);
-                    output = true;
-                }
-                //update the packet according to the immediate actions of this flow rule.
-                packet = updatePacket(packet, flowEntry.treatment().immediate()).build();
-
-                //save the deferred rules for later
-                deferredInstructions.addAll(flowEntry.treatment().deferred());
-
-                //If the flow requires to clear deferred actions we do so for all the ones we encountered.
-                if (flowEntry.treatment().clearedDeferred()) {
-                    deferredInstructions.clear();
-                }
-
-                //On table 10 OFDPA needs two rules to apply the vlan if none and then to transition to the next table.
-                if (needsSecondTable10Flow(flowEntry, isOfdpaHardware)) {
-
-                    //Let's get the packet vlanId instruction
-                    VlanIdCriterion packetVlanIdCriterion =
-                            (VlanIdCriterion) packet.getCriterion(Criterion.Type.VLAN_VID);
-
-                    //Let's get the flow entry vlan mod instructions
-                    ModVlanIdInstruction entryModVlanIdInstruction = (ModVlanIdInstruction) flowEntry.treatment()
-                            .immediate().stream()
-                            .filter(instruction -> instruction instanceof ModVlanIdInstruction)
-                            .findFirst().orElse(null);
-
-                    //If the entry modVlan is not null we need to make sure that the packet has been updated and there
-                    // is a flow rule that matches on same criteria and with updated vlanId
-                    if (entryModVlanIdInstruction != null) {
-
-                        FlowEntry secondVlanFlow = getSecondFlowEntryOnTable10(packet, in,
-                                packetVlanIdCriterion, entryModVlanIdInstruction);
-
-                        //We found the flow that we expected
-                        if (secondVlanFlow != null) {
-                            flows.add(secondVlanFlow);
-                        } else {
-                            trace.addResultMessage("Missing forwarding rule for tagged packet on " + in);
-                            computePath(completePath, trace, null);
-                            return trace;
-                        }
-                    }
-
-                }
-
-            }
-        }
-
-        //Creating a modifiable builder for the output packet
-        Builder builder = DefaultTrafficSelector.builder();
-        packet.criteria().forEach(builder::add);
-
-        //Adding all the flows to the trace
-        trace.addFlowsForDevice(in.deviceId(), ImmutableList.copyOf(flows));
-
-        List<PortNumber> outputPorts = new ArrayList<>();
-        List<FlowEntry> outputFlowEntries = handleFlows(trace, packet, in, outputFlows, builder, outputPorts);
-
-
-        log.debug("Handling Groups");
-        //Analyze Groups
-        List<Group> groups = new ArrayList<>();
-
-        Collection<FlowEntry> nonOutputFlows = flows;
-        nonOutputFlows.removeAll(outputFlowEntries);
-
-        //Handling groups pointed at by immediate instructions
-        for (FlowEntry entry : flows) {
-            getGroupsFromInstructions(trace, groups, entry.treatment().immediate(),
-                    entry.deviceId(), builder, outputPorts, in, completePath);
-        }
-
-        //If we have deferred instructions at this point we handle them.
-        if (deferredInstructions.size() > 0) {
-            builder = handleDeferredActions(trace, packet, in, deferredInstructions, outputPorts, groups, completePath);
-
-        }
-        packet = builder.build();
-
-        log.debug("Output Packet {}", packet);
-        return trace;
-    }
-
-    private List<FlowEntry> handleFlows(StaticPacketTrace trace, TrafficSelector packet, ConnectPoint in,
-                                        List<FlowEntry> outputFlows, Builder builder, List<PortNumber> outputPorts) {
-        //TODO optimization
-        //outputFlows contains also last rule of device, so we need filtering for OUTPUT instructions.
-        List<FlowEntry> outputFlowEntries = outputFlows.stream().filter(flow -> flow.treatment()
-                .allInstructions().stream().filter(instruction -> instruction.type()
-                        .equals(Instruction.Type.OUTPUT)).count() > 0).collect(Collectors.toList());
-
-        if (outputFlowEntries.size() > 1) {
-            trace.addResultMessage("More than one flow rule with OUTPUT instruction");
-            log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", packet);
-        }
-
-        if (outputFlowEntries.size() == 1) {
-
-            OutputInstruction outputInstruction = (OutputInstruction) outputFlowEntries.get(0).treatment()
-                    .allInstructions().stream()
-                    .filter(instruction -> {
-                        return instruction.type().equals(Instruction.Type.OUTPUT);
-                    }).findFirst().get();
-
-            //FIXME using GroupsInDevice for output even if flows.
-            buildOutputFromDevice(trace, in, builder, outputPorts, outputInstruction, ImmutableList.of());
-
-        }
-        return outputFlowEntries;
-    }
-
-    private boolean multipleRoutes(StaticPacketTrace trace) {
-        boolean multipleRoutes = false;
-        IPCriterion ipCriterion = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST));
-        IpAddress ip = null;
-        if (ipCriterion != null) {
-            ip = ipCriterion.ip().address();
-        } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST) != null) {
-            ip = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST)).ip().address();
-        }
-        if (ip != null) {
-            Optional<ResolvedRoute> optionalRoute = routeNib.longestPrefixLookup(ip);
-            if (optionalRoute.isPresent()) {
-                ResolvedRoute route = optionalRoute.get();
-                multipleRoutes = routeNib.getAllResolvedRoutes(route.prefix()).size() > 1;
-            }
-        }
-        return multipleRoutes;
-    }
-
-    /**
-     * Handles the specific case where the Input is the controller.
-     * Note that the in port is used as a convenience to store the port of the controller even if the packet in
-     * from a controller should not have a physical input port. The in port from the Controller is used to make sure
-     * the flood to all active physical ports of the device.
-     *
-     * @param trace the trace
-     * @param in    the controller port
-     * @return the augmented trace.
-     */
-    private StaticPacketTrace inputFromController(StaticPacketTrace trace, ConnectPoint in) {
-        EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) trace.getInitialPacket()
-                .getCriterion(Criterion.Type.ETH_TYPE);
-        //If the packet is LLDP or BDDP we flood it on all active ports of the switch.
-        if (ethTypeCriterion != null && (ethTypeCriterion.ethType().equals(EtherType.LLDP.ethType())
-                || ethTypeCriterion.ethType().equals(EtherType.BDDP.ethType()))) {
-            //get the active ports
-            List<Port> enabledPorts = deviceNib.getPorts(in.deviceId()).stream()
-                    .filter(Port::isEnabled)
-                    .collect(Collectors.toList());
-            //build an output from each one
-            enabledPorts.forEach(port -> {
-                GroupsInDevice output = new GroupsInDevice(new ConnectPoint(port.element().id(), port.number()),
-                        ImmutableList.of(), trace.getInitialPacket());
-                trace.addGroupOutputPath(in.deviceId(), output);
-            });
-            return trace;
-        }
-        return null;
-    }
-
-    private boolean needsSecondTable10Flow(FlowEntry flowEntry, boolean isOfdpaHardware) {
-        return isOfdpaHardware && flowEntry.table().equals(IndexTableId.of(10))
-                && flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID) != null
-                && ((VlanIdCriterion) flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID))
-                .vlanId().equals(VlanId.NONE);
-    }
-
-    /**
-     * Method that finds a flow rule on table 10 that matches the packet and the VLAN of the already
-     * found rule on table 10. This is because OFDPA needs two rules on table 10, first to apply the rule,
-     * second to transition to following table
-     *
-     * @param packet                    the incoming packet
-     * @param in                        the input connect point
-     * @param packetVlanIdCriterion     the vlan criterion from the packet
-     * @param entryModVlanIdInstruction the entry vlan instruction
-     * @return the second flow entry that matched
-     */
-    private FlowEntry getSecondFlowEntryOnTable10(TrafficSelector packet, ConnectPoint in,
-                                                  VlanIdCriterion packetVlanIdCriterion,
-                                                  ModVlanIdInstruction entryModVlanIdInstruction) {
-        FlowEntry secondVlanFlow = null;
-        //Check the packet has been update from the first rule.
-        if (packetVlanIdCriterion.vlanId().equals(entryModVlanIdInstruction.vlanId())) {
-            //find a rule on the same table that matches the vlan and
-            // also all the other elements of the flow such as input port
-            secondVlanFlow = Lists.newArrayList(flowNib.getFlowEntriesByState(in.deviceId(),
-                    FlowEntry.FlowEntryState.ADDED)
-                    .iterator()).stream()
-                    .filter(entry -> {
-                        return entry.table().equals(IndexTableId.of(10));
-                    })
-                    .filter(entry -> {
-                        VlanIdCriterion criterion = (VlanIdCriterion) entry.selector()
-                                .getCriterion(Criterion.Type.VLAN_VID);
-                        return criterion != null && match(packet, entry)
-                                && criterion.vlanId().equals(entryModVlanIdInstruction.vlanId());
-                    }).findFirst().orElse(null);
-
-        }
-        return secondVlanFlow;
-    }
-
-
-    /**
-     * Handles table 27 in Ofpda which is a fixed table not visible to any controller that handles Mpls Labels.
-     *
-     * @param packet the incoming packet
-     * @return the updated packet
-     */
-    private TrafficSelector handleOfdpa27FixedTable(StaticPacketTrace trace, TrafficSelector packet) {
-        log.debug("Handling table 27 on OFDPA, removing mpls ETH Type and change mpls label");
-        Criterion mplsCriterion = packet.getCriterion(Criterion.Type.ETH_TYPE);
-        ImmutableList.Builder<Instruction> builder = ImmutableList.builder();
-
-        //If the pakcet comes in with the expected elements we update it as per OFDPA spec.
-        if (mplsCriterion != null && ((EthTypeCriterion) mplsCriterion).ethType()
-                .equals(EtherType.MPLS_UNICAST.ethType())) {
-            //TODO update with parsing with eth MPLS pop Instruction for treating label an bos
-            Instruction ethInstruction = Instructions.popMpls(((EthTypeCriterion) trace.getInitialPacket()
-                    .getCriterion(Criterion.Type.ETH_TYPE)).ethType());
-            //FIXME what do we use as L3_Unicast mpls Label ?
-            //translateInstruction(builder, ethInstruction);
-            builder.add(ethInstruction);
-        }
-        packet = updatePacket(packet, builder.build()).build();
-        return packet;
-    }
-
-    /**
-     * Finds the flow entry with the minimun next table Id.
-     *
-     * @param deviceId  the device to search
-     * @param currentId the current id. the search will use this as minimum
-     * @return the flow entry with the minimum table Id after the given one.
-     */
-    private FlowEntry findNextTableIdEntry(DeviceId deviceId, int currentId) {
-
-        final Comparator<FlowEntry> comparator = Comparator.comparing((FlowEntry f) -> ((IndexTableId) f.table()).id());
-        return Lists.newArrayList(flowNib.getFlowEntriesByState(deviceId, FlowEntry.FlowEntryState.ADDED)
-                .iterator()).stream()
-                .filter(f -> ((IndexTableId) f.table()).id() > currentId).min(comparator).orElse(null);
-    }
-
-    private Builder handleDeferredActions(StaticPacketTrace trace, TrafficSelector packet,
-                                          ConnectPoint in, List<Instruction> deferredInstructions,
-                                          List<PortNumber> outputPorts, List<Group> groups,
-                                          List<ConnectPoint> completePath) {
-
-        //Update the packet with the deferred instructions
-        Builder builder = updatePacket(packet, deferredInstructions);
-
-        //Gather any output instructions from the deferred instruction
-        List<Instruction> outputFlowInstruction = deferredInstructions.stream().filter(instruction -> {
-            return instruction.type().equals(Instruction.Type.OUTPUT);
-        }).collect(Collectors.toList());
-
-        //We are considering deferred instructions from flows, there can only be one output.
-        if (outputFlowInstruction.size() > 1) {
-            trace.addResultMessage("More than one flow rule with OUTPUT instruction");
-            log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", packet);
-        }
-        //If there is one output let's go through that
-        if (outputFlowInstruction.size() == 1) {
-            buildOutputFromDevice(trace, in, builder, outputPorts, (OutputInstruction) outputFlowInstruction.get(0),
-                    ImmutableList.of());
-        }
-        //If there is no output let's see if there any deferred instruction point to groups.
-        if (outputFlowInstruction.size() == 0) {
-            getGroupsFromInstructions(trace, groups, deferredInstructions,
-                    in.deviceId(), builder, outputPorts, in, completePath);
-        }
-        return builder;
-    }
-
-    /**
-     * Gets group information from instructions.
-     *
-     * @param trace           the trace we are building
-     * @param groupsForDevice the set of groups for this device
-     * @param instructions    the set of instructions we are searching for groups.
-     * @param deviceId        the device we are considering
-     * @param builder         the builder of the input packet
-     * @param outputPorts     the output ports for that packet
-     */
-    private void getGroupsFromInstructions(StaticPacketTrace trace, List<Group> groupsForDevice,
-                                           List<Instruction> instructions, DeviceId deviceId,
-                                           Builder builder, List<PortNumber> outputPorts,
-                                           ConnectPoint in, List<ConnectPoint> completePath) {
-        List<Instruction> groupInstructionlist = new ArrayList<>();
-        // sort instructions according to priority (larger Instruction.Type ENUM constant first)
-        // which enables to treat other actions before the OUTPUT action
-        //TODO improve the priority scheme according to the OpenFlow ActionSet spec
-        List<Instruction> instructionsSorted = new ArrayList<>();
-        instructionsSorted.addAll(instructions);
-        instructionsSorted.sort((instr1, instr2) -> {
-            return Integer.compare(instr2.type().ordinal(), instr1.type().ordinal());
-        });
-
-        for (Instruction instruction : instructionsSorted) {
-            log.debug("Considering Instruction {}", instruction);
-            //if the instruction is not group we need to update the packet or add the output
-            //to the possible outputs for this packet
-            if (!instruction.type().equals(Instruction.Type.GROUP)) {
-                //if the instruction is not group we need to update the packet or add the output
-                //to the possible outputs for this packet
-                if (instruction.type().equals(Instruction.Type.OUTPUT)) {
-                    buildOutputFromDevice(trace, in, builder, outputPorts,
-                            (OutputInstruction) instruction, ImmutableList.copyOf(groupsForDevice));
-                    //clearing the groups because we start from the top.
-                    groupsForDevice.clear();
-                } else {
-                    builder = translateInstruction(builder, instruction);
-                }
-            } else {
-                //if the instuction is pointing to a group we need to get the group
-                groupInstructionlist.add(instruction);
-            }
-        }
-        //handle all the internal instructions pointing to a group.
-        for (Instruction instr : groupInstructionlist) {
-            GroupInstruction groupInstruction = (GroupInstruction) instr;
-            Group group = Lists.newArrayList(groupNib.getGroups(deviceId)).stream().filter(groupInternal -> {
-                return groupInternal.id().equals(groupInstruction.groupId());
-            }).findAny().orElse(null);
-            if (group == null) {
-                trace.addResultMessage("Null group for Instruction " + instr);
-                trace.setSuccess(false);
-                break;
-            }
-            if (group.buckets().buckets().size() == 0) {
-                trace.addResultMessage("Group " + group.id() + " has no buckets");
-                trace.setSuccess(false);
-                computePath(completePath, trace, null);
-                break;
-            }
-
-            //Cycle in each of the group's buckets and add them to the groups for this Device.
-            for (GroupBucket bucket : group.buckets().buckets()) {
-
-                //add the group to the traversed groups
-                if (!groupsForDevice.contains(group)) {
-                    groupsForDevice.add(group);
-                }
-
-                getGroupsFromInstructions(trace, groupsForDevice, bucket.treatment().allInstructions(),
-                        deviceId, builder, outputPorts, in, completePath);
-            }
-        }
-    }
-
-    /**
-     * Check if the output is the input port, if so adds a dop result message, otherwise builds
-     * a possible output from this device.
-     *
-     * @param trace             the trace
-     * @param in                the input connect point
-     * @param builder           the packet builder
-     * @param outputPorts       the list of output ports for this device
-     * @param outputInstruction the output instruction
-     * @param groupsForDevice   the groups we output from
-     */
-    private void buildOutputFromDevice(StaticPacketTrace trace, ConnectPoint in, Builder builder,
-                                       List<PortNumber> outputPorts, OutputInstruction outputInstruction,
-                                       List<Group> groupsForDevice) {
-        ConnectPoint output = new ConnectPoint(in.deviceId(), outputInstruction.port());
-
-        outputPorts.add(outputInstruction.port());
-
-        GroupsInDevice device = new GroupsInDevice(output, groupsForDevice, builder.build());
-        if (trace.getGroupOuputs(output.deviceId()) != null
-                && trace.getGroupOuputs(output.deviceId()).contains(device)) {
-            return;
-        }
-        trace.addGroupOutputPath(in.deviceId(),
-                new GroupsInDevice(output, groupsForDevice, builder.build()));
-    }
-
-    /**
-     * Applies all give instructions to the input packet.
-     *
-     * @param packet       the input packet
-     * @param instructions the set of instructions
-     * @return the packet with the applied instructions
-     */
-    private Builder updatePacket(TrafficSelector packet, List<Instruction> instructions) {
-        Builder newSelector = DefaultTrafficSelector.builder();
-        packet.criteria().forEach(newSelector::add);
-        //FIXME optimize
-        for (Instruction instruction : instructions) {
-            newSelector = translateInstruction(newSelector, instruction);
-        }
-        return newSelector;
-    }
-
-    /**
-     * Applies an instruction to the packet in the form of a selector.
-     *
-     * @param newSelector the packet selector
-     * @param instruction the instruction to be translated
-     * @return the new selector with the applied instruction
-     */
-    private Builder translateInstruction(Builder newSelector, Instruction instruction) {
-        log.debug("Translating instruction {}", instruction);
-        log.debug("New Selector {}", newSelector.build());
-        //TODO add as required
-        Criterion criterion = null;
-        switch (instruction.type()) {
-            case L2MODIFICATION:
-                L2ModificationInstruction l2Instruction = (L2ModificationInstruction) instruction;
-                switch (l2Instruction.subtype()) {
-                    case VLAN_ID:
-                        ModVlanIdInstruction vlanIdInstruction =
-                                (ModVlanIdInstruction) instruction;
-                        VlanId id = vlanIdInstruction.vlanId();
-                        criterion = Criteria.matchVlanId(id);
-                        break;
-                    case VLAN_POP:
-                        criterion = Criteria.matchVlanId(VlanId.NONE);
-                        break;
-                    case MPLS_PUSH:
-                        ModMplsHeaderInstruction mplsEthInstruction =
-                                (ModMplsHeaderInstruction) instruction;
-                        criterion = Criteria.matchEthType(mplsEthInstruction.ethernetType().toShort());
-                        break;
-                    case MPLS_POP:
-                        ModMplsHeaderInstruction mplsPopInstruction =
-                                (ModMplsHeaderInstruction) instruction;
-                        criterion = Criteria.matchEthType(mplsPopInstruction.ethernetType().toShort());
-
-                        //When popping MPLS we remove label and BOS
-                        TrafficSelector temporaryPacket = newSelector.build();
-                        if (temporaryPacket.getCriterion(Criterion.Type.MPLS_LABEL) != null) {
-                            Builder noMplsSelector = DefaultTrafficSelector.builder();
-                            temporaryPacket.criteria().stream().filter(c -> {
-                                return !c.type().equals(Criterion.Type.MPLS_LABEL) &&
-                                        !c.type().equals(Criterion.Type.MPLS_BOS);
-                            }).forEach(noMplsSelector::add);
-                            newSelector = noMplsSelector;
-                        }
-
-                        break;
-                    case MPLS_LABEL:
-                        ModMplsLabelInstruction mplsLabelInstruction =
-                                (ModMplsLabelInstruction) instruction;
-                        criterion = Criteria.matchMplsLabel(mplsLabelInstruction.label());
-                        newSelector.matchMplsBos(true);
-                        break;
-                    case ETH_DST:
-                        ModEtherInstruction modEtherDstInstruction =
-                                (ModEtherInstruction) instruction;
-                        criterion = Criteria.matchEthDst(modEtherDstInstruction.mac());
-                        break;
-                    case ETH_SRC:
-                        ModEtherInstruction modEtherSrcInstruction =
-                                (ModEtherInstruction) instruction;
-                        criterion = Criteria.matchEthSrc(modEtherSrcInstruction.mac());
-                        break;
-                    default:
-                        log.debug("Unsupported L2 Instruction");
-                        break;
-                }
-                break;
-            default:
-                log.debug("Unsupported Instruction");
-                break;
-        }
-        if (criterion != null) {
-            log.debug("Adding criterion {}", criterion);
-            newSelector.add(criterion);
-        }
-        return newSelector;
-    }
-
-    /**
-     * Finds the rule in the device that mathces the input packet and has the highest priority.
-     *
-     * @param packet  the input packet
-     * @param in      the connect point the packet comes in from
-     * @param tableId the table to search
-     * @return the flow entry
-     */
-    private FlowEntry matchHighestPriority(TrafficSelector packet, ConnectPoint in, TableId tableId) {
-        //Computing the possible match rules.
-        final Comparator<FlowEntry> comparator = Comparator.comparing(FlowRule::priority);
-        return Lists.newArrayList(flowNib.getFlowEntriesByState(in.deviceId(), FlowEntry.FlowEntryState.ADDED)
-                .iterator()).stream()
-                .filter(flowEntry -> {
-                    return flowEntry.table().equals(tableId);
-                })
-                .filter(flowEntry -> {
-                    return match(packet, flowEntry);
-                }).max(comparator).orElse(null);
-    }
-
-    /**
-     * Matches the packet with the given flow entry.
-     *
-     * @param packet    the packet to match
-     * @param flowEntry the flow entry to match the packet against
-     * @return true if the packet matches the flow.
-     */
-    private boolean match(TrafficSelector packet, FlowEntry flowEntry) {
-        return flowEntry.selector().criteria().stream().allMatch(criterion -> {
-            Criterion.Type type = criterion.type();
-            //If the criterion has IP we need to do LPM to establish matching.
-            if (type.equals(Criterion.Type.IPV4_SRC) || type.equals(Criterion.Type.IPV4_DST) ||
-                    type.equals(Criterion.Type.IPV6_SRC) || type.equals(Criterion.Type.IPV6_DST)) {
-                return matchIp(packet, (IPCriterion) criterion);
-                //we check that the packet contains the criterion provided by the flow rule.
-            } else if (type.equals(Criterion.Type.ETH_SRC_MASKED)) {
-                return matchMac(packet, (EthCriterion) criterion, false);
-            } else if (type.equals(Criterion.Type.ETH_DST_MASKED)) {
-                return matchMac(packet, (EthCriterion) criterion, true);
-            } else {
-                return packet.criteria().contains(criterion);
-            }
-        });
-    }
-
-    /**
-     * Checks if the packet has an dst or src IP and if that IP matches the subnet of the ip criterion.
-     *
-     * @param packet    the incoming packet
-     * @param criterion the criterion to match
-     * @return true if match
-     */
-    private boolean matchIp(TrafficSelector packet, IPCriterion criterion) {
-        IPCriterion matchCriterion = (IPCriterion) packet.getCriterion(criterion.type());
-        //if the packet does not have an IPv4 or IPv6 criterion we return true
-        if (matchCriterion == null) {
-            return false;
-        }
-        try {
-            log.debug("Checking if {} is under {}", matchCriterion.ip(), criterion.ip());
-            Subnet subnet = Subnet.createInstance(criterion.ip().toString());
-            return subnet.isInSubnet(matchCriterion.ip().address().toInetAddress());
-        } catch (UnknownHostException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Checks if the packet has a dst or src MAC and if that Mac matches the mask of the mac criterion.
-     *
-     * @param packet       the incoming packet
-     * @param hitCriterion the criterion to match
-     * @param dst          true if we are checking DST MAC
-     * @return true if match
-     */
-    private boolean matchMac(TrafficSelector packet, EthCriterion hitCriterion, boolean dst) {
-        //Packet can have only one EthCriterion
-        EthCriterion matchCriterion;
-        if (dst) {
-            matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 -> {
-                return criterion1.type().equals(Criterion.Type.ETH_DST_MASKED) ||
-                        criterion1.type().equals(Criterion.Type.ETH_DST);
-            }).findFirst().orElse(null);
-        } else {
-            matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 -> {
-                return criterion1.type().equals(Criterion.Type.ETH_SRC_MASKED) ||
-                        criterion1.type().equals(Criterion.Type.ETH_SRC);
-            }).findFirst().orElse(null);
-        }
-        //if the packet does not have an ETH criterion we return true
-        if (matchCriterion == null) {
-            return true;
-        }
-        log.debug("Checking if {} is under {}/{}", matchCriterion.mac(), hitCriterion.mac(), hitCriterion.mask());
-        return compareMac(matchCriterion.mac(), hitCriterion.mac(), hitCriterion.mask());
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java
deleted file mode 100644
index 097fa92..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2018-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.t3.impl;
-
-import com.google.common.collect.ImmutableMap;
-import org.onlab.packet.MacAddress;
-
-import java.util.Map;
-
-/**
- * Utility class for the troubleshooting tool.
- */
-final class TroubleshootUtils {
-
-    private TroubleshootUtils() {
-        //Banning construction
-    }
-
-    /**
-     * Map defining if a specific driver is for a HW switch.
-     */
-    //Done with builder() instead of of() for clarity
-    static Map<String, Boolean> hardwareOfdpaMap = ImmutableMap.<String, Boolean>builder()
-            .put("ofdpa", true)
-            .put("ofdpa3", true)
-            .put("qmx-ofdpa3", true)
-            .put("as7712-32x-premium", true)
-            .put("as5912-54x-premium", true)
-            .put("as5916-54x-premium", true)
-            .put("accton-ofdpa3", true)
-            .put("delta-ofdpa3", true)
-            .put("znyx-ofdpa", true)
-            .build();
-
-    /**
-     * Checks if the Mac Address is inside a range between the min MAC and the mask.
-     * @param macAddress the MAC address to check
-     * @param minAddr the min MAC address
-     * @param maskAddr the mask
-     * @return true if in range, false otherwise.
-     */
-    static boolean compareMac(MacAddress macAddress, MacAddress minAddr, MacAddress maskAddr) {
-        byte[] mac = macAddress.toBytes();
-        byte[] min = minAddr.toBytes();
-        byte[] mask = maskAddr.toBytes();
-        boolean inRange = true;
-
-        int i = 0;
-
-        //if mask is 00 stop
-        while (inRange && i < mask.length && (mask[i] & 0xFF) != 0) {
-            int ibmac = mac[i] & 0xFF;
-            int ibmin = min[i] & 0xFF;
-            int ibmask = mask[i] & 0xFF;
-            if (ibmask == 255) {
-                inRange = ibmac == ibmin;
-            } else if (ibmac < ibmin || ibmac >= ibmask) {
-                inRange = false;
-                break;
-            }
-            i++;
-        }
-
-        return inRange;
-    }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/package-info.java
deleted file mode 100644
index dfcc294..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-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.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics implementation.
- */
-package org.onosproject.t3.impl;
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/package-info.java
deleted file mode 100644
index 2dae6e2..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-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.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics.
- */
-package org.onosproject.t3;
diff --git a/apps/t3/app/src/test/java/org/onosproject/t3/impl/T3TestObjects.java b/apps/t3/app/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
deleted file mode 100644
index 2ec39b4..0000000
--- a/apps/t3/app/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright 2018-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.t3.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.DefaultApplicationId;
-import org.onosproject.core.GroupId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultFlowEntry;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.group.DefaultGroup;
-import org.onosproject.net.group.DefaultGroupBucket;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.group.GroupBuckets;
-import org.onosproject.net.provider.ProviderId;
-
-/**
- * Helper class for objects related to the Troubleshoot Manager Test.
- */
-final class T3TestObjects {
-
-    private T3TestObjects() {
-        //banning construction
-    }
-
-    private static final String HOST_ONE_MAC = "00:00:00:00:00:01";
-    private static final String HOST_TWO_MAC = "00:00:00:00:00:02";
-    private static final String HOST_ONE_VLAN = "None";
-    private static final String HOST_TWO_VLAN = "None";
-    private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
-    private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
-    private static final String HOST_DUAL_HOMED_MAC = "00:00:00:00:00:03";
-    private static final String HOST_DUAL_HOMED_VLAN = "None";
-    private static final String HOST_DUAL_HOMED = HOST_DUAL_HOMED_MAC + "/" + HOST_DUAL_HOMED_VLAN;
-
-    //offline device
-    static final DeviceId OFFLINE_DEVICE = DeviceId.deviceId("offlineDevice");
-
-    //Single Flow Test
-    static final DeviceId SINGLE_FLOW_DEVICE = DeviceId.deviceId("SingleFlowDevice");
-    private static final TrafficSelector SINGLE_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .build();
-
-    private static final TrafficTreatment OUTPUT_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.portNumber(2)).build();
-    private static final FlowRule SINGLE_FLOW = DefaultFlowEntry.builder().forDevice(SINGLE_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(OUTPUT_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry SINGLE_FLOW_ENTRY = new DefaultFlowEntry(SINGLE_FLOW);
-
-    static final ConnectPoint SINGLE_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(SINGLE_FLOW_DEVICE + "/" + 1);
-
-    static final ConnectPoint SINGLE_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(SINGLE_FLOW_DEVICE + "/" + 2);
-
-    //same output as input
-    static final DeviceId SAME_OUTPUT_FLOW_DEVICE = DeviceId.deviceId("sameOutputDevice");
-
-    private static final TrafficTreatment SAME_OUTPUT_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.portNumber(1)).build();
-    private static final FlowRule SAME_OUTPUT_FLOW = DefaultFlowEntry.builder().forDevice(SAME_OUTPUT_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(SAME_OUTPUT_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry SAME_OUTPUT_FLOW_ENTRY = new DefaultFlowEntry(SAME_OUTPUT_FLOW);
-
-    static final ConnectPoint SAME_OUTPUT_FLOW_CP = ConnectPoint.deviceConnectPoint(SAME_OUTPUT_FLOW_DEVICE + "/" + 1);
-
-    //ARP
-    static final DeviceId ARP_FLOW_DEVICE = DeviceId.deviceId("ArpDevice");
-
-    private static final TrafficSelector ARP_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchEthType(EthType.EtherType.ARP.ethType().toShort())
-            .build();
-
-    private static final TrafficTreatment ARP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.CONTROLLER).build();
-    private static final FlowRule ARP_FLOW = DefaultFlowEntry.builder().forDevice(ARP_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(ARP_FLOW_SELECTOR)
-            .withTreatment(ARP_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry ARP_FLOW_ENTRY = new DefaultFlowEntry(ARP_FLOW);
-
-    static final ConnectPoint ARP_FLOW_CP = ConnectPoint.deviceConnectPoint(ARP_FLOW_DEVICE + "/" + 1);
-
-
-    //Dual Flow Test
-    static final DeviceId DUAL_FLOW_DEVICE = DeviceId.deviceId("DualFlowDevice");
-    private static final TrafficTreatment TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setVlanId(VlanId.vlanId((short) 100))
-            .transition(10)
-            .build();
-    private static final TrafficSelector VLAN_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchVlanId(VlanId.vlanId((short) 100))
-            .build();
-    private static final FlowRule FIRST_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(TRANSITION_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry FIRST_FLOW_ENTRY = new DefaultFlowEntry(FIRST_FLOW);
-    private static final FlowRule SECOND_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_FLOW_DEVICE)
-            .forTable(10)
-            .withPriority(100)
-            .withSelector(VLAN_FLOW_SELECTOR)
-            .withTreatment(OUTPUT_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry SECOND_FLOW_ENTRY = new DefaultFlowEntry(SECOND_FLOW);
-
-    static final ConnectPoint DUAL_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(DUAL_FLOW_DEVICE + "/" + 1);
-
-    static final ConnectPoint DUAL_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(DUAL_FLOW_DEVICE + "/" + 2);
-
-    //Flow and Group Test
-    static final DeviceId GROUP_FLOW_DEVICE = DeviceId.deviceId("GroupFlowDevice");
-
-    private static final GroupId GROUP_ID = GroupId.valueOf(1);
-
-    private static final TrafficTreatment GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .pushMpls()
-            .setMpls(MplsLabel.mplsLabel(100))
-            .group(GROUP_ID)
-            .build();
-    private static final FlowRule GROUP_FLOW = DefaultFlowEntry.builder().forDevice(GROUP_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(GROUP_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry GROUP_FLOW_ENTRY = new DefaultFlowEntry(GROUP_FLOW);
-
-    private static final TrafficTreatment OUTPUT_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
-            .popMpls(EthType.EtherType.IPV4.ethType())
-            .setOutput(PortNumber.portNumber(2)).build();
-
-    private static final GroupBucket BUCKET = DefaultGroupBucket.createSelectGroupBucket(OUTPUT_GROUP_TREATMENT);
-
-    private static final GroupBuckets BUCKETS = new GroupBuckets(ImmutableList.of(BUCKET));
-
-    static final Group GROUP = new DefaultGroup(GROUP_ID, GROUP_FLOW_DEVICE, Group.Type.SELECT, BUCKETS);
-
-    static final ConnectPoint GROUP_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(GROUP_FLOW_DEVICE + "/" + 1);
-
-    static final ConnectPoint GROUP_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(GROUP_FLOW_DEVICE + "/" + 2);
-
-    // Group multiple action order test
-    static final DeviceId ACTION_ORDER_DEVICE = DeviceId.deviceId("ActionOrderDevice");
-    private static final VlanId ACTION_ORDER_VLAN_ID = VlanId.vlanId("999");
-    static final MplsLabel ACTION_ORDER_MPLS_LABEL = MplsLabel.mplsLabel("999");
-    private static final TrafficTreatment ACTION_ORDER_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .pushVlan()
-            .setVlanId(ACTION_ORDER_VLAN_ID)
-            .group(GROUP_ID)
-            .build();
-    private static final FlowRule ACTION_ORDER_FLOW = DefaultFlowEntry.builder().forDevice(ACTION_ORDER_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(ACTION_ORDER_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry ACTION_ORDER_FLOW_ENTRY = new DefaultFlowEntry(ACTION_ORDER_FLOW);
-    private static final TrafficTreatment ACTION_ORDER_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
-            // make lower order actions come first
-            .setOutput(PortNumber.portNumber(2))
-            .setMpls(ACTION_ORDER_MPLS_LABEL)
-            .pushMpls()
-            .popVlan()
-            .build();
-    private static final GroupBucket ACTION_ORDER_BUCKET = DefaultGroupBucket
-            .createSelectGroupBucket(ACTION_ORDER_GROUP_TREATMENT);
-    private static final GroupBuckets ACTION_ORDER_BUCKETS = new GroupBuckets(ImmutableList.of(ACTION_ORDER_BUCKET));
-    static final Group ACTION_ORDER_GROUP = new DefaultGroup(
-            GROUP_ID, ACTION_ORDER_DEVICE, Group.Type.SELECT, ACTION_ORDER_BUCKETS);
-    static final ConnectPoint ACTION_ORDER_IN_CP = ConnectPoint.deviceConnectPoint(ACTION_ORDER_DEVICE + "/" + 1);
-    static final ConnectPoint ACTION_ORDER_OUT_CP = ConnectPoint.deviceConnectPoint(ACTION_ORDER_DEVICE + "/" + 2);
-
-    //topology
-
-    static final DeviceId TOPO_FLOW_DEVICE = DeviceId.deviceId("SingleFlowDevice1");
-
-    static final DeviceId TOPO_FLOW_2_DEVICE = DeviceId.deviceId("SingleFlowDevice2");
-
-    static final DeviceId TOPO_FLOW_3_DEVICE = DeviceId.deviceId("SingleFlowDevice3");
-
-    private static final TrafficSelector TOPO_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
-            .build();
-
-    private static final FlowRule TOPO_SINGLE_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(TOPO_FLOW_SELECTOR)
-            .withTreatment(OUTPUT_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry TOPO_SINGLE_FLOW_ENTRY = new DefaultFlowEntry(TOPO_SINGLE_FLOW);
-
-    static final ConnectPoint TOPO_FLOW_1_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_DEVICE + "/" + 1);
-
-    static final ConnectPoint TOPO_FLOW_1_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_DEVICE + "/" + 2);
-
-    static final ConnectPoint TOPO_FLOW_2_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_2_DEVICE + "/" + 1);
-
-    static final ConnectPoint TOPO_FLOW_2_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_2_DEVICE + "/" + 2);
-
-    static final ConnectPoint TOPO_FLOW_3_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 1);
-
-    static final ConnectPoint TOPO_FLOW_3_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 2);
-
-
-    //Topology with Groups
-
-    static final DeviceId TOPO_GROUP_FLOW_DEVICE = DeviceId.deviceId("TopoGroupFlowDevice");
-
-    private static final TrafficSelector TOPO_SECOND_INPUT_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(3))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
-            .build();
-
-    private static final FlowRule TOPO_SECOND_INPUT_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(TOPO_SECOND_INPUT_FLOW_SELECTOR)
-            .withTreatment(OUTPUT_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    private static final TrafficTreatment OUTPUT_2_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.portNumber(3)).build();
-
-
-    private static final GroupId TOPO_GROUP_ID = GroupId.valueOf(1);
-
-    private static final TrafficTreatment TOPO_GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .group(TOPO_GROUP_ID)
-            .build();
-    private static final FlowRule TOPO_GROUP_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_GROUP_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(TOPO_FLOW_SELECTOR)
-            .withTreatment(TOPO_GROUP_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry TOPO_GROUP_FLOW_ENTRY = new DefaultFlowEntry(TOPO_GROUP_FLOW);
-
-    private static final GroupBucket BUCKET_2 = DefaultGroupBucket.createSelectGroupBucket(OUTPUT_2_FLOW_TREATMENT);
-
-    private static final GroupBuckets BUCKETS_MULTIPLE = new GroupBuckets(ImmutableList.of(BUCKET, BUCKET_2));
-
-    static final Group TOPO_GROUP = new DefaultGroup(TOPO_GROUP_ID, TOPO_GROUP_FLOW_DEVICE,
-            Group.Type.SELECT, BUCKETS_MULTIPLE);
-
-    static final FlowEntry TOPO_SECOND_INPUT_FLOW_ENTRY = new DefaultFlowEntry(TOPO_SECOND_INPUT_FLOW);
-
-    static final DeviceId TOPO_FLOW_4_DEVICE = DeviceId.deviceId("SingleFlowDevice4");
-
-    static final ConnectPoint TOPO_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 1);
-
-    static final ConnectPoint TOPO_FLOW_OUT_CP_1 = ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 2);
-
-    protected static final ConnectPoint TOPO_FLOW_OUT_CP_2 =
-            ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 3);
-
-    static final ConnectPoint TOPO_FLOW_4_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_4_DEVICE + "/" + 1);
-
-    static final ConnectPoint TOPO_FLOW_3_IN_2_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 3);
-
-    static final ConnectPoint TOPO_FLOW_4_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_4_DEVICE + "/" + 2);
-
-
-    //hardware
-
-    static final DeviceId HARDWARE_DEVICE = DeviceId.deviceId("HardwareDevice");
-
-    static final ConnectPoint HARDWARE_DEVICE_IN_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE + "/" + 1);
-
-    static final ConnectPoint HARDWARE_DEVICE_OUT_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE + "/" + 2);
-
-    private static final TrafficSelector HARDWARE_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .build();
-
-    private static final TrafficTreatment HW_TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .pushMpls()
-            .transition(27)
-            .build();
-
-    private static final FlowRule HARDWARE_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(HARDWARE_FLOW_SELECTOR)
-            .withTreatment(HW_TRANSITION_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry HARDWARE_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_FLOW);
-
-    private static final TrafficSelector HARDWARE_ETH_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
-            .build();
-
-    private static final FlowRule HARDWARE_ETH_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
-            .forTable(30)
-            .withPriority(100)
-            .withSelector(HARDWARE_ETH_FLOW_SELECTOR)
-            .withTreatment(OUTPUT_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry HARDWARE_ETH_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_ETH_FLOW);
-
-    //HW Double Rule on 10
-
-    static final DeviceId HARDWARE_DEVICE_10 = DeviceId.deviceId("HardwareDevice10");
-
-    static final ConnectPoint HARDWARE_DEVICE_10_IN_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE_10 + "/" + 1);
-
-    static final ConnectPoint HARDWARE_DEVICE_10_OUT_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE_10 + "/" + 2);
-
-    private static final TrafficSelector HARDWARE_10_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .matchVlanId(VlanId.NONE)
-            .build();
-
-    private static final TrafficTreatment HARDWARE_10_TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setVlanId(VlanId.vlanId("10"))
-            .transition(20)
-            .build();
-
-    private static final FlowRule HARDWARE_DEVICE_10_FLOW = DefaultFlowEntry.builder().forDevice(HARDWARE_DEVICE_10)
-            .forTable(10)
-            .withPriority(100)
-            .withSelector(HARDWARE_10_FLOW_SELECTOR)
-            .withTreatment(HARDWARE_10_TRANSITION_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry HARDWARE_10_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_DEVICE_10_FLOW);
-
-    private static final TrafficSelector HARDWARE_10_SECOND_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchVlanId(VlanId.vlanId("10"))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
-            .build();
-
-    private static final FlowRule HARDWARE_10_SECOND_FLOW = DefaultFlowEntry.builder().forDevice(HARDWARE_DEVICE_10)
-            .forTable(10)
-            .withPriority(100)
-            .withSelector(HARDWARE_10_SECOND_SELECTOR)
-            .withTreatment(HARDWARE_10_TRANSITION_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry HARDWARE_10_SECOND_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_10_SECOND_FLOW);
-
-    private static final FlowRule HARDWARE_10_OUTPUT_FLOW = DefaultFlowEntry.builder().forDevice(HARDWARE_DEVICE_10)
-            .forTable(20)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(OUTPUT_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry HARDWARE_10_OUTPUT_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_10_OUTPUT_FLOW);
-
-    //Dual Links
-    // - (1) Device 1 (2-3) - (1-4) Device 2 (2-3) - (1-2) Device 3 (3) -
-    static final DeviceId DUAL_LINK_1 = DeviceId.deviceId("DualLink1");
-    static final DeviceId DUAL_LINK_2 = DeviceId.deviceId("DualLink2");
-    static final DeviceId DUAL_LINK_3 = DeviceId.deviceId("DualLink3");
-
-    static final ConnectPoint DUAL_LINK_1_CP_1_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_1 + "/" + 1);
-    static final ConnectPoint DUAL_LINK_1_CP_2_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_1 + "/" + 2);
-    static final ConnectPoint DUAL_LINK_1_CP_3_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_1 + "/" + 3);
-    static final ConnectPoint DUAL_LINK_2_CP_1_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 1);
-    static final ConnectPoint DUAL_LINK_2_CP_4_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 4);
-    static final ConnectPoint DUAL_LINK_2_CP_2_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 2);
-    static final ConnectPoint DUAL_LINK_2_CP_3_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 3);
-    static final ConnectPoint DUAL_LINK_3_CP_1_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_3 + "/" + 1);
-    static final ConnectPoint DUAL_LINK_3_CP_2_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_3 + "/" + 2);
-    static final ConnectPoint DUAL_LINK_3_CP_3_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_3 + "/" + 3);
-
-    //match on port 1 and point to group for device 1 and 2
-    private static final TrafficTreatment DUAL_LINK_1_GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .pushMpls()
-            .setMpls(MplsLabel.mplsLabel(100))
-            .group(GROUP_ID)
-            .build();
-    private static final FlowRule DUAL_LINK_1_GROUP_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_LINK_1)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(DUAL_LINK_1_GROUP_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry DUAL_LINK_1_GROUP_FLOW_ENTRY = new DefaultFlowEntry(DUAL_LINK_1_GROUP_FLOW);
-
-    //Match on port 4 and point to group for device 2
-    private static final TrafficSelector DUAL_LINK_2_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(4))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .build();
-
-    private static final FlowRule DUAL_LINK_2_GROUP_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_LINK_2)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(DUAL_LINK_2_FLOW_SELECTOR)
-            .withTreatment(DUAL_LINK_1_GROUP_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry DUAL_LINK_2_GROUP_FLOW_ENTRY = new DefaultFlowEntry(DUAL_LINK_2_GROUP_FLOW);
-
-    //Flows for device 3 to ouput on port 3
-    private static final TrafficTreatment DUAL_LINK_1_OUTPUT_TREATMENT = DefaultTrafficTreatment.builder()
-            .popMpls(EthType.EtherType.IPV4.ethType())
-            .setOutput(PortNumber.portNumber(3)).build();
-
-    private static final TrafficSelector DUAL_LINK_3_FLOW_SELECTOR_1 = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .build();
-    private static final FlowRule DUAL_LINK_3_FLOW_1 = DefaultFlowEntry.builder().forDevice(DUAL_LINK_3)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(DUAL_LINK_3_FLOW_SELECTOR_1)
-            .withTreatment(DUAL_LINK_1_OUTPUT_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry DUAL_LINK_3_FLOW_ENTRY = new DefaultFlowEntry(DUAL_LINK_3_FLOW_1);
-
-    private static final TrafficSelector DUAL_LINK_3_FLOW_SELECTOR_2 = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(2))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .build();
-    private static final FlowRule DUAL_LINK_3_FLOW_2 = DefaultFlowEntry.builder().forDevice(DUAL_LINK_3)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(DUAL_LINK_3_FLOW_SELECTOR_2)
-            .withTreatment(DUAL_LINK_1_OUTPUT_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-
-    static final FlowEntry DUAL_LINK_3_FLOW_ENTRY_2 = new DefaultFlowEntry(DUAL_LINK_3_FLOW_2);
-
-    //Group with two buckets to output on port 2 and 3 of device 1 and 2
-
-    private static final GroupBucket BUCKET_2_DUAL =
-            DefaultGroupBucket.createSelectGroupBucket(DUAL_LINK_1_OUTPUT_TREATMENT);
-
-    private static final GroupBuckets BUCKETS_DUAL = new GroupBuckets(ImmutableList.of(BUCKET, BUCKET_2_DUAL));
-
-    static final Group DUAL_LINK_GROUP = new DefaultGroup(GROUP_ID, DUAL_LINK_1, Group.Type.SELECT, BUCKETS_DUAL);
-
-    //Clear Deferred
-    static final DeviceId DEFERRED_1 = DeviceId.deviceId("Deferred");
-
-    static final ConnectPoint DEFERRED_CP_1_IN = ConnectPoint.deviceConnectPoint(DEFERRED_1 + "/" + 1);
-    static final ConnectPoint DEFERRED_CP_2_OUT = ConnectPoint.deviceConnectPoint(DEFERRED_1 + "/" + 2);
-
-    //match on port 1 and apply deferred actions
-    private static final TrafficTreatment DEFERRED_1_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .transition(10)
-            .deferred()
-            .pushMpls()
-            .setMpls(MplsLabel.mplsLabel(100))
-            .build();
-    private static final FlowRule DEFERRED_FLOW = DefaultFlowEntry.builder().forDevice(DEFERRED_1)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(DEFERRED_1_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry DEFERRED_FLOW_ENTRY = new DefaultFlowEntry(DEFERRED_FLOW);
-
-    //Multicast Flow and Group Test
-    static final DeviceId MULTICAST_GROUP_FLOW_DEVICE = DeviceId.deviceId("MulticastGroupFlowDevice");
-
-    private static final TrafficSelector MULTICAST_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPDst(IpPrefix.valueOf("224.0.0.1/32"))
-            .matchEthDst(MacAddress.valueOf("01:00:5e:00:00:01"))
-            .build();
-
-    private static final FlowRule MULTICAST_GROUP_FLOW =
-            DefaultFlowEntry.builder().forDevice(MULTICAST_GROUP_FLOW_DEVICE)
-                    .forTable(0)
-                    .withPriority(100)
-                    .withSelector(MULTICAST_FLOW_SELECTOR)
-                    .withTreatment(GROUP_FLOW_TREATMENT)
-                    .fromApp(new DefaultApplicationId(0, "TestApp"))
-                    .makePermanent()
-                    .build();
-
-    static final FlowEntry MULTICAST_GROUP_FLOW_ENTRY = new DefaultFlowEntry(MULTICAST_GROUP_FLOW);
-
-    static final Group MULTICAST_GROUP = new DefaultGroup(GROUP_ID, MULTICAST_GROUP_FLOW_DEVICE,
-            Group.Type.SELECT, BUCKETS_MULTIPLE);
-
-    static final ConnectPoint MULTICAST_IN_CP = ConnectPoint.deviceConnectPoint(MULTICAST_GROUP_FLOW_DEVICE + "/" + 1);
-
-    static final ConnectPoint MULTICAST_OUT_CP = ConnectPoint.deviceConnectPoint(MULTICAST_GROUP_FLOW_DEVICE + "/" + 3);
-
-    static final ConnectPoint MULTICAST_OUT_CP_2 =
-            ConnectPoint.deviceConnectPoint(MULTICAST_GROUP_FLOW_DEVICE + "/" + 2);
-
-    //match on port 1, clear deferred actions and output
-    private static final TrafficTreatment DEFERRED_CLEAR_1_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .wipeDeferred()
-            .setOutput(PortNumber.portNumber(2))
-            .build();
-    private static final FlowRule DEFERRED_CLEAR_FLOW = DefaultFlowEntry.builder().forDevice(DEFERRED_1)
-            .forTable(10)
-            .withPriority(100)
-            .withSelector(SINGLE_FLOW_SELECTOR)
-            .withTreatment(DEFERRED_CLEAR_1_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry DEFERRED_CLEAR_FLOW_ENTRY = new DefaultFlowEntry(DEFERRED_CLEAR_FLOW);
-
-    //LLDP
-
-    static final DeviceId LLDP_FLOW_DEVICE = DeviceId.deviceId("LldpDevice");
-
-    private static final TrafficSelector LLDP_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchEthType(EthType.EtherType.LLDP.ethType().toShort())
-            .build();
-
-    private static final TrafficTreatment LLDP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.CONTROLLER).build();
-    private static final FlowRule LLDP_FLOW = DefaultFlowEntry.builder().forDevice(LLDP_FLOW_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(LLDP_FLOW_SELECTOR)
-            .withTreatment(LLDP_FLOW_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry LLDP_FLOW_ENTRY = new DefaultFlowEntry(LLDP_FLOW);
-
-    static final ConnectPoint LLDP_FLOW_CP = ConnectPoint.deviceConnectPoint(LLDP_FLOW_DEVICE + "/" + 1);
-
-    //No Buckets
-
-    static final DeviceId NO_BUCKET_DEVICE = DeviceId.deviceId("nobucket");
-
-    private static final TrafficSelector NO_BUCKET_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .build();
-
-    private static final GroupId NO_BUCKET_GROUP_ID = GroupId.valueOf(1);
-
-    private static final TrafficTreatment NO_BUCKET_TREATMENT = DefaultTrafficTreatment.builder()
-            .group(NO_BUCKET_GROUP_ID)
-            .build();
-    private static final FlowRule NO_BUCKET_FLOW = DefaultFlowEntry.builder().forDevice(NO_BUCKET_DEVICE)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(NO_BUCKET_SELECTOR)
-            .withTreatment(NO_BUCKET_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry NO_BUCKET_ENTRY = new DefaultFlowEntry(NO_BUCKET_FLOW);
-
-    private static final GroupBuckets NO_BUCKETS = new GroupBuckets(ImmutableList.of());
-
-    static final Group NO_BUCKET_GROUP =
-            new DefaultGroup(NO_BUCKET_GROUP_ID, NO_BUCKET_DEVICE, Group.Type.SELECT, NO_BUCKETS);
-
-    static final ConnectPoint NO_BUCKET_CP = ConnectPoint.deviceConnectPoint(NO_BUCKET_DEVICE + "/" + 1);
-
-    //Dual Homing
-
-    static final DeviceId DUAL_HOME_DEVICE_1 = DeviceId.deviceId("DualHomeDevice1");
-
-    static final DeviceId DUAL_HOME_DEVICE_2 = DeviceId.deviceId("DualHomeDevice2");
-
-    static final DeviceId DUAL_HOME_DEVICE_3 = DeviceId.deviceId("DualHomeDevice3");
-
-    static final ConnectPoint DUAL_HOME_CP_1_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 1);
-    static final ConnectPoint DUAL_HOME_CP_1_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 2);
-    static final ConnectPoint DUAL_HOME_CP_1_3 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 3);
-
-    static final ConnectPoint DUAL_HOME_CP_2_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_2 + "/" + 1);
-    static final ConnectPoint DUAL_HOME_CP_2_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_2 + "/" + 2);
-
-    static final ConnectPoint DUAL_HOME_CP_3_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_3 + "/" + 1);
-    static final ConnectPoint DUAL_HOME_CP_3_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_3 + "/" + 2);
-
-
-    private static final TrafficSelector  DUAL_HOME_INPUT_FLOW_SELECTOR = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .build();
-
-    private static final GroupId DUAL_HOME_GROUP_ID = GroupId.valueOf(1);
-
-    private static final TrafficTreatment DUAL_HOME_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
-            .group(DUAL_HOME_GROUP_ID)
-            .build();
-    private static final FlowRule DUAL_HOME_INPUT_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_HOME_DEVICE_1)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(DUAL_HOME_INPUT_FLOW_SELECTOR)
-            .withTreatment(DUAL_HOME_GROUP_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry DUAL_HOME_FLOW_ENTRY = new DefaultFlowEntry(DUAL_HOME_INPUT_FLOW);
-
-    private static final TrafficTreatment DUAL_HOME_OUTPUT_1_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.portNumber(2)).build();
-    private static final TrafficTreatment DUAL_HOME_OUTPUT_2_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.portNumber(3)).build();
-
-    private static final GroupBucket BUCKET_1_DUAL_HOMED =
-            DefaultGroupBucket.createSelectGroupBucket(DUAL_HOME_OUTPUT_1_FLOW_TREATMENT);
-
-    private static final GroupBucket BUCKET_2_DUAL_HOMED =
-            DefaultGroupBucket.createSelectGroupBucket(DUAL_HOME_OUTPUT_2_FLOW_TREATMENT);
-
-    private static final GroupBuckets BUCKETS_MULTIPLE_DUAL = new GroupBuckets(ImmutableList.of(BUCKET_1_DUAL_HOMED,
-            BUCKET_2_DUAL_HOMED));
-
-    static final Group DUAL_HOME_GROUP = new DefaultGroup(DUAL_HOME_GROUP_ID, DUAL_HOME_DEVICE_1,
-            Group.Type.SELECT, BUCKETS_MULTIPLE_DUAL);
-
-    private static final TrafficTreatment DUAL_HOME_TREATMENT = DefaultTrafficTreatment.builder()
-            .setOutput(PortNumber.portNumber("2"))
-            .build();
-    private static final FlowRule DUAL_HOME_OUT_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_HOME_DEVICE_2)
-            .forTable(0)
-            .withPriority(100)
-            .withSelector(DUAL_HOME_INPUT_FLOW_SELECTOR)
-            .withTreatment(DUAL_HOME_TREATMENT)
-            .fromApp(new DefaultApplicationId(0, "TestApp"))
-            .makePermanent()
-            .build();
-    static final FlowEntry DUAL_HOME_OUT_FLOW_ENTRY = new DefaultFlowEntry(DUAL_HOME_OUT_FLOW);
-
-    //helper elements
-
-    static final String MASTER_1 = "Master1";
-
-    static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_ONE), MacAddress.valueOf(100),
-            VlanId.NONE, new HostLocation(SINGLE_FLOW_DEVICE, PortNumber.portNumber(2), 0),
-            ImmutableSet.of(IpAddress.valueOf("127.0.0.2")));
-
-    static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_TWO), MacAddress.valueOf(100),
-            VlanId.NONE, new HostLocation(TOPO_FLOW_3_DEVICE, PortNumber.portNumber(2), 0),
-            ImmutableSet.of(IpAddress.valueOf("127.0.0.3")));
-
-    static final Host DUAL_HOME_H = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_DUAL_HOMED),
-            MacAddress.valueOf(HOST_DUAL_HOMED_MAC),
-            VlanId.NONE, ImmutableSet.of(new HostLocation(DUAL_HOME_DEVICE_2, PortNumber.portNumber(2), 0),
-            new HostLocation(DUAL_HOME_DEVICE_3, PortNumber.portNumber(2), 0)),
-            ImmutableSet.of(IpAddress.valueOf("127.0.0.4")), true, DefaultAnnotations.builder().build());
-
-    static final TrafficSelector PACKET_OK = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
-            .matchVlanId(VlanId.NONE)
-            .build();
-
-    static final TrafficSelector PACKET_OK_TOPO = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
-            .build();
-
-    static final TrafficSelector PACKET_ARP = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPDst(IpPrefix.valueOf("255.255.255.255/32"))
-            .matchEthType(EthType.EtherType.ARP.ethType().toShort())
-            .build();
-
-    static final TrafficSelector PACKET_LLDP = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchEthType(EthType.EtherType.LLDP.ethType().toShort())
-            .build();
-
-    static final TrafficSelector PACKET_OK_MULTICAST = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
-            .matchEthDst(MacAddress.valueOf("01:00:5e:00:00:01"))
-            .matchIPDst(IpPrefix.valueOf("224.0.0.1/32"))
-            .build();
-
-    static final TrafficSelector PACKET_DUAL_HOME = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.4/32"))
-            .build();
-
-    static final TrafficSelector PACKET_FAIL = DefaultTrafficSelector.builder()
-            .matchInPort(PortNumber.portNumber(1))
-            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
-            .matchIPDst(IpPrefix.valueOf("127.0.0.99/32"))
-            .build();
-}
diff --git a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java b/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
deleted file mode 100644
index d1eba21..0000000
--- a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
+++ /dev/null
@@ -1,695 +0,0 @@
-/*
- * Copyright 2018-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.t3.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.ChassisId;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.MplsCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.RouteNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.slf4j.Logger;
-
-import java.util.Optional;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.onosproject.net.Device.Type.SWITCH;
-import static org.onosproject.t3.impl.T3TestObjects.*;
-import static org.onosproject.t3.impl.TroubleshootManager.PACKET_TO_CONTROLLER;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Test Class for Troubleshoot Manager.
- */
-public class TroubleshootManagerTest {
-
-    private static final Logger log = getLogger(TroubleshootManager.class);
-
-    private TroubleshootManager mngr;
-
-    @Before
-    public void setUp() throws Exception {
-        mngr = new TroubleshootManager();
-
-        mngr.flowNib = new TestFlowRuleService();
-        mngr.groupNib = new TestGroupService();
-        mngr.hostNib = new TestHostService();
-        mngr.linkNib = new TestLinkService();
-        mngr.deviceNib = new TestDeviceService();
-        mngr.driverNib = new TestDriverService();
-        mngr.mastershipNib = new TestMastershipService();
-        mngr.edgePortNib = new TestEdgePortService();
-        mngr.routeNib = new TestRouteService();
-
-        assertNotNull("Manager should not be null", mngr);
-
-        assertNotNull("Flow rule Service should not be null", mngr.flowNib);
-        assertNotNull("Group Service should not be null", mngr.groupNib);
-        assertNotNull("Host Service should not be null", mngr.hostNib);
-        assertNotNull("Link Service should not be null", mngr.linkNib);
-        assertNotNull("Device Service should not be null", mngr.deviceNib);
-        assertNotNull("Driver Service should not be null", mngr.driverNib);
-        assertNotNull("Mastership Service should not be null", mngr.driverNib);
-        assertNotNull("EdgePort Service should not be null", mngr.driverNib);
-        assertNotNull("Route Service should not be null", mngr.routeNib);
-    }
-
-    /**
-     * Tests failure on non existent device.
-     */
-    @Test(expected = NullPointerException.class)
-    public void nonExistentDevice() {
-        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("nonexistent" + "/1"));
-    }
-
-    /**
-     * Tests failure on offline device.
-     */
-    @Test
-    public void offlineDevice() {
-        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint(OFFLINE_DEVICE + "/1"));
-        assertNotNull("Trace should not be null", traceFail);
-        assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
-    }
-
-    /**
-     * Tests failure on same output.
-     */
-    @Test
-    public void sameOutput() {
-        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, SAME_OUTPUT_FLOW_CP);
-        assertNotNull("Trace should not be null", traceFail);
-        assertTrue("Trace should be unsuccessful",
-                traceFail.resultMessage().contains("is same as initial input"));
-        log.info("trace {}", traceFail.resultMessage());
-    }
-
-    /**
-     * Tests ARP to controller.
-     */
-    @Test
-    public void arpToController() {
-        StaticPacketTrace traceSuccess = mngr.trace(PACKET_ARP, ARP_FLOW_CP);
-        assertNotNull("Trace should not be null", traceSuccess);
-        assertTrue("Trace should be successful",
-                traceSuccess.resultMessage().contains(PACKET_TO_CONTROLLER));
-        assertTrue("Master should be Master1",
-                traceSuccess.resultMessage().contains(MASTER_1));
-        ConnectPoint connectPoint = traceSuccess.getGroupOuputs(ARP_FLOW_DEVICE).get(0).getOutput();
-        assertEquals("Packet Should go to CONTROLLER", PortNumber.CONTROLLER, connectPoint.port());
-        assertNull("VlanId should be null", traceSuccess.getGroupOuputs(ARP_FLOW_DEVICE).get(0)
-                .getFinalPacket().getCriterion(Criterion.Type.VLAN_VID));
-        log.info("trace {}", traceSuccess.resultMessage());
-    }
-
-
-    /**
-     * Tests failure on device with no flows.
-     */
-    @Test
-    public void noFlows() {
-        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("test/1"));
-        assertNotNull("Trace should not be null", traceFail);
-        assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
-        log.info("trace {}", traceFail.resultMessage());
-    }
-
-    /**
-     * Test group with no buckets.
-     */
-    @Test
-    public void noBucketsTest() throws Exception {
-
-        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, NO_BUCKET_CP);
-        assertNotNull("Trace should not be null", traceFail);
-        assertTrue("Trace should be unsuccessful",
-                traceFail.resultMessage().contains("no buckets"));
-        log.info("trace {}", traceFail.resultMessage());
-
-    }
-
-    /**
-     * Test a single flow rule that has output port in it.
-     */
-    @Test
-    public void testSingleFlowRule() {
-
-        testSuccess(PACKET_OK, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE, SINGLE_FLOW_OUT_CP, 1, 1);
-
-        testFailure(PACKET_FAIL, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE);
-    }
-
-    /**
-     * Tests two flow rule the last one of which has output port in it.
-     */
-    @Test
-    public void testDualFlowRule() {
-
-        //Test Success
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE,
-                DUAL_FLOW_OUT_CP, 1, 1);
-
-        //Testing Vlan
-        Criterion criterion = traceSuccess.getGroupOuputs(DUAL_FLOW_DEVICE).get(0).
-                getFinalPacket().getCriterion(Criterion.Type.VLAN_VID);
-        assertNotNull("Packet Should have Vlan", criterion);
-
-        VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion;
-
-        assertEquals("Vlan should be 100", VlanId.vlanId((short) 100), vlanIdCriterion.vlanId());
-
-        //Test Faliure
-        testFailure(PACKET_FAIL, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE);
-
-    }
-
-    /**
-     * Test a single flow rule that points to a group with output port in it.
-     */
-    @Test
-    public void flowAndGroup() throws Exception {
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, GROUP_FLOW_IN_CP, GROUP_FLOW_DEVICE,
-                GROUP_FLOW_OUT_CP, 1, 1);
-
-        assertTrue("Wrong Output Group", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
-                .get(0).getGroups().contains(GROUP));
-        assertEquals("Packet should not have MPLS Label", EthType.EtherType.IPV4.ethType(),
-                ((EthTypeCriterion) traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
-                        .get(0).getFinalPacket().getCriterion(Criterion.Type.ETH_TYPE)).ethType());
-        assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
-                .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));
-        assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
-                .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_BOS));
-
-    }
-
-    /**
-     * Test a single flow rule that points to a group with multiple actions
-     * that need to be executed in the order specified in the OpenFlow spec.
-     */
-    @Test
-    public void testGroupMultipleActionsOrdered() {
-
-        StaticPacketTrace traceSuccess = testSuccess(
-                PACKET_OK, ACTION_ORDER_IN_CP, ACTION_ORDER_DEVICE, ACTION_ORDER_OUT_CP, 1, 1);
-
-        assertEquals("Packet should not have VLAN ID",
-                VlanId.NONE,
-                ((VlanIdCriterion) traceSuccess.getGroupOuputs(ACTION_ORDER_DEVICE)
-                        .get(0).getFinalPacket().getCriterion(Criterion.Type.VLAN_VID)).vlanId());
-        assertEquals("Packet should have MPLS label",
-                ACTION_ORDER_MPLS_LABEL,
-                ((MplsCriterion) traceSuccess.getGroupOuputs(ACTION_ORDER_DEVICE)
-                        .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL)).label());
-
-    }
-
-    /**
-     * Test path through a 3 device topology.
-     */
-    @Test
-    public void singlePathTopology() throws Exception {
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_1_IN_CP,
-                TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 1, 1);
-
-        assertTrue("Incorrect path",
-                traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_IN_CP));
-        assertTrue("Incorrect path",
-                traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_OUT_CP));
-        assertTrue("Incorrect path",
-                traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_3_IN_CP));
-
-    }
-
-    /**
-     * Test path through a 4 device topology with first device that has groups with multiple output buckets.
-     */
-    @Test
-    public void testGroupTopo() throws Exception {
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_IN_CP,
-                TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 2, 1);
-
-        log.info("{}", traceSuccess);
-
-        assertTrue("Incorrect groups",
-                traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(0).getGroups().contains(TOPO_GROUP));
-        assertTrue("Incorrect bucket",
-                traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(1).getGroups().contains(TOPO_GROUP));
-    }
-
-    /**
-     * Test HW support in a single device with 2 flow rules to check hit of static HW rules.
-     */
-    @Test
-    public void hardwareTest() throws Exception {
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, HARDWARE_DEVICE_IN_CP,
-                HARDWARE_DEVICE, HARDWARE_DEVICE_OUT_CP, 1, 1);
-
-        assertEquals("wrong ETH type", EthType.EtherType.IPV4.ethType(),
-                ((EthTypeCriterion) traceSuccess.getGroupOuputs(HARDWARE_DEVICE).get(0).getFinalPacket()
-                        .getCriterion(Criterion.Type.ETH_TYPE)).ethType());
-
-    }
-
-    /**
-     * Test that HW has two rules on table 10 for untagged packets.
-     */
-    @Test
-    public void hardwareTable10Test() throws Exception {
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, HARDWARE_DEVICE_10_IN_CP,
-                HARDWARE_DEVICE_10, HARDWARE_DEVICE_10_OUT_CP, 1, 1);
-
-        assertTrue("Second flow rule is absent", traceSuccess.getFlowsForDevice(HARDWARE_DEVICE_10)
-                .contains(HARDWARE_10_SECOND_FLOW_ENTRY));
-
-    }
-
-    /**
-     * Test dual links between 3 topology elements.
-     */
-    @Test
-    public void dualLinks() throws Exception {
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_LINK_1_CP_1_IN,
-                DUAL_LINK_3, DUAL_LINK_3_CP_3_OUT, 4, 1);
-
-        //TODO tests
-
-    }
-
-    /**
-     * Test proper clear deferred behaviour.
-     */
-    @Test
-    public void clearDeferred() throws Exception {
-
-        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DEFERRED_CP_1_IN,
-                DEFERRED_1, DEFERRED_CP_2_OUT, 1, 1);
-
-        assertNull("MPLS should have been not applied due to clear deferred", traceSuccess
-                .getGroupOuputs(DEFERRED_1).get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));
-
-    }
-
-
-    /**
-     * Test LLDP output to controller.
-     */
-    @Test
-    public void lldpToController() {
-        StaticPacketTrace traceSuccess = mngr.trace(PACKET_LLDP, LLDP_FLOW_CP);
-        assertNotNull("Trace should not be null", traceSuccess);
-        assertTrue("Trace should be successful",
-                traceSuccess.resultMessage().contains("Packet goes to the controller"));
-        assertTrue("Master should be Master1",
-                traceSuccess.resultMessage().contains(MASTER_1));
-        ConnectPoint connectPoint = traceSuccess.getGroupOuputs(LLDP_FLOW_DEVICE).get(0).getOutput();
-        assertEquals("Packet Should go to CONTROLLER", PortNumber.CONTROLLER, connectPoint.port());
-        log.info("trace {}", traceSuccess.resultMessage());
-    }
-
-    /**
-     * Test multicast in single device.
-     */
-    @Test
-    public void multicastTest() throws Exception {
-
-        StaticPacketTrace traceSuccess = mngr.trace(PACKET_OK_MULTICAST, MULTICAST_IN_CP);
-
-        log.info("trace {}", traceSuccess);
-
-        log.info("trace {}", traceSuccess.resultMessage());
-
-        assertNotNull("trace should not be null", traceSuccess);
-        assertEquals("Trace should have " + 2 + " output", 2,
-                traceSuccess.getGroupOuputs(MULTICAST_GROUP_FLOW_DEVICE).size());
-        assertEquals("Trace should only have " + 2 + "output", 2,
-                traceSuccess.getCompletePaths().size());
-        assertTrue("Trace should be successful",
-                traceSuccess.resultMessage().contains("reached output"));
-        assertEquals("Incorrect Output CP", MULTICAST_OUT_CP_2,
-                traceSuccess.getGroupOuputs(MULTICAST_GROUP_FLOW_DEVICE).get(0).getOutput());
-        assertEquals("Incorrect Output CP", MULTICAST_OUT_CP,
-                traceSuccess.getGroupOuputs(MULTICAST_GROUP_FLOW_DEVICE).get(1).getOutput());
-
-    }
-
-    /**
-     * Tests dual homing of a host.
-     */
-    @Test
-    public void dualhomedTest() throws Exception {
-        StaticPacketTrace traceSuccess = mngr.trace(PACKET_DUAL_HOME, DUAL_HOME_CP_1_1);
-
-        assertNotNull("trace should not be null", traceSuccess);
-        assertTrue("Should have 2 output paths", traceSuccess.getCompletePaths().size() == 2);
-        assertTrue("Should contain proper path", traceSuccess.getCompletePaths()
-                .contains(ImmutableList.of(DUAL_HOME_CP_1_1, DUAL_HOME_CP_1_2, DUAL_HOME_CP_2_1, DUAL_HOME_CP_2_2)));
-        assertTrue("Should contain proper path", traceSuccess.getCompletePaths()
-                .contains(ImmutableList.of(DUAL_HOME_CP_1_1, DUAL_HOME_CP_1_3, DUAL_HOME_CP_3_1, DUAL_HOME_CP_3_2)));
-
-    }
-
-
-    private StaticPacketTrace testSuccess(TrafficSelector packet, ConnectPoint in, DeviceId deviceId, ConnectPoint out,
-                                          int paths, int outputs) {
-        StaticPacketTrace traceSuccess = mngr.trace(packet, in);
-
-        log.info("trace {}", traceSuccess);
-
-        log.info("trace {}", traceSuccess.resultMessage());
-
-        assertNotNull("trace should not be null", traceSuccess);
-        assertEquals("Trace should have " + outputs + " output", outputs,
-                traceSuccess.getGroupOuputs(deviceId).size());
-        assertEquals("Trace should only have " + paths + "output", paths, traceSuccess.getCompletePaths().size());
-        assertTrue("Trace should be successful",
-                traceSuccess.resultMessage().contains("Reached required destination Host"));
-        assertEquals("Incorrect Output CP", out,
-                traceSuccess.getGroupOuputs(deviceId).get(0).getOutput());
-
-        return traceSuccess;
-    }
-
-    private void testFailure(TrafficSelector packet, ConnectPoint in, DeviceId deviceId) {
-        StaticPacketTrace traceFail = mngr.trace(packet, in);
-
-        log.info("trace {}", traceFail.resultMessage());
-
-        assertNotNull("Trace should not be null", traceFail);
-        assertNull("Trace should have 0 output", traceFail.getGroupOuputs(deviceId));
-    }
-
-    private class TestFlowRuleService extends FlowNib {
-        @Override
-        public Iterable<FlowEntry> getFlowEntriesByState(DeviceId deviceId, FlowEntry.FlowEntryState state) {
-            if (deviceId.equals(SINGLE_FLOW_DEVICE)) {
-                return ImmutableList.of(SINGLE_FLOW_ENTRY);
-            } else if (deviceId.equals(DUAL_FLOW_DEVICE)) {
-                return ImmutableList.of(FIRST_FLOW_ENTRY, SECOND_FLOW_ENTRY);
-            } else if (deviceId.equals(GROUP_FLOW_DEVICE)) {
-                return ImmutableList.of(GROUP_FLOW_ENTRY);
-            } else if (deviceId.equals(TOPO_FLOW_DEVICE) ||
-                    deviceId.equals(TOPO_FLOW_2_DEVICE) ||
-                    deviceId.equals(TOPO_FLOW_3_DEVICE) ||
-                    deviceId.equals(TOPO_FLOW_4_DEVICE)) {
-                return ImmutableList.of(TOPO_SINGLE_FLOW_ENTRY, TOPO_SECOND_INPUT_FLOW_ENTRY);
-            } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
-                return ImmutableList.of(TOPO_GROUP_FLOW_ENTRY);
-            } else if (deviceId.equals(HARDWARE_DEVICE)) {
-                return ImmutableList.of(HARDWARE_ETH_FLOW_ENTRY, HARDWARE_FLOW_ENTRY);
-            } else if (deviceId.equals(SAME_OUTPUT_FLOW_DEVICE)) {
-                return ImmutableList.of(SAME_OUTPUT_FLOW_ENTRY);
-            } else if (deviceId.equals(ARP_FLOW_DEVICE)) {
-                return ImmutableList.of(ARP_FLOW_ENTRY);
-            } else if (deviceId.equals(DUAL_LINK_1)) {
-                return ImmutableList.of(DUAL_LINK_1_GROUP_FLOW_ENTRY);
-            } else if (deviceId.equals(DUAL_LINK_2)) {
-                return ImmutableList.of(DUAL_LINK_1_GROUP_FLOW_ENTRY, DUAL_LINK_2_GROUP_FLOW_ENTRY);
-            } else if (deviceId.equals(DUAL_LINK_3)) {
-                return ImmutableList.of(DUAL_LINK_3_FLOW_ENTRY, DUAL_LINK_3_FLOW_ENTRY_2);
-            } else if (deviceId.equals(DEFERRED_1)) {
-                return ImmutableList.of(DEFERRED_FLOW_ENTRY, DEFERRED_CLEAR_FLOW_ENTRY);
-            } else if (deviceId.equals(HARDWARE_DEVICE_10)) {
-                return ImmutableList.of(HARDWARE_10_FLOW_ENTRY, HARDWARE_10_SECOND_FLOW_ENTRY,
-                        HARDWARE_10_OUTPUT_FLOW_ENTRY);
-            } else if (deviceId.equals(LLDP_FLOW_DEVICE)) {
-                return ImmutableList.of(LLDP_FLOW_ENTRY);
-            } else if (deviceId.equals(MULTICAST_GROUP_FLOW_DEVICE)) {
-                return ImmutableList.of(MULTICAST_GROUP_FLOW_ENTRY);
-            } else if (deviceId.equals(NO_BUCKET_DEVICE)) {
-                return ImmutableList.of(NO_BUCKET_ENTRY);
-            } else if (deviceId.equals(DUAL_HOME_DEVICE_1)) {
-                return ImmutableList.of(DUAL_HOME_FLOW_ENTRY);
-            } else if (deviceId.equals(DUAL_HOME_DEVICE_2) || deviceId.equals(DUAL_HOME_DEVICE_3)) {
-                return ImmutableList.of(DUAL_HOME_OUT_FLOW_ENTRY);
-            } else if (deviceId.equals(ACTION_ORDER_DEVICE)) {
-                return ImmutableList.of(ACTION_ORDER_FLOW_ENTRY);
-            }
-            return ImmutableList.of();
-        }
-    }
-
-    private class TestGroupService extends GroupNib {
-        @Override
-        public Iterable<Group> getGroups(DeviceId deviceId) {
-            if (deviceId.equals(GROUP_FLOW_DEVICE)) {
-                return ImmutableList.of(GROUP);
-            } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
-                return ImmutableList.of(TOPO_GROUP);
-            } else if (deviceId.equals(DUAL_LINK_1) || deviceId.equals(DUAL_LINK_2)) {
-                return ImmutableList.of(DUAL_LINK_GROUP);
-            } else if (deviceId.equals(MULTICAST_GROUP_FLOW_DEVICE)) {
-                return ImmutableList.of(MULTICAST_GROUP);
-            } else if (deviceId.equals(NO_BUCKET_DEVICE)) {
-                return ImmutableList.of(NO_BUCKET_GROUP);
-            } else if (deviceId.equals(DUAL_HOME_DEVICE_1)) {
-                return ImmutableList.of(DUAL_HOME_GROUP);
-            } else if (deviceId.equals(ACTION_ORDER_DEVICE)) {
-                return ImmutableList.of(ACTION_ORDER_GROUP);
-            }
-            return ImmutableList.of();
-        }
-    }
-
-    private class TestHostService extends HostNib {
-        @Override
-        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
-            if (connectPoint.equals(TOPO_FLOW_3_OUT_CP)) {
-                return ImmutableSet.of(H2);
-            } else if (connectPoint.equals(DUAL_LINK_1_CP_2_OUT) || connectPoint.equals(DUAL_LINK_1_CP_3_OUT) ||
-                    connectPoint.equals(DUAL_LINK_2_CP_2_OUT) || connectPoint.equals(DUAL_LINK_2_CP_3_OUT)) {
-                return ImmutableSet.of();
-            }
-            if (connectPoint.equals(SINGLE_FLOW_OUT_CP) ||
-                    connectPoint.equals(DUAL_FLOW_OUT_CP) ||
-                    connectPoint.equals(GROUP_FLOW_OUT_CP) ||
-                    connectPoint.equals(HARDWARE_DEVICE_OUT_CP) ||
-                    connectPoint.equals(HARDWARE_DEVICE_10_OUT_CP) ||
-                    connectPoint.equals(DEFERRED_CP_2_OUT) ||
-                    connectPoint.equals(DUAL_LINK_3_CP_3_OUT) ||
-                    connectPoint.equals(ACTION_ORDER_OUT_CP)) {
-                return ImmutableSet.of(H1);
-            }
-            if (connectPoint.equals(DUAL_HOME_CP_2_2) || connectPoint.equals(DUAL_HOME_CP_3_2)) {
-                return ImmutableSet.of(DUAL_HOME_H);
-            }
-            return ImmutableSet.of();
-        }
-
-        @Override
-        public Set<Host> getHostsByMac(MacAddress mac) {
-            if (mac.equals(H1.mac())) {
-                return ImmutableSet.of(H1);
-            } else if (mac.equals(H2.mac())) {
-                return ImmutableSet.of(H2);
-            } else if (mac.equals(DUAL_HOME_H.mac())) {
-                return ImmutableSet.of(DUAL_HOME_H);
-            }
-            return ImmutableSet.of();
-        }
-
-        @Override
-        public Set<Host> getHostsByIp(IpAddress ip) {
-            if ((H1.ipAddresses().contains(ip))) {
-                return ImmutableSet.of(H1);
-            } else if ((H2.ipAddresses().contains(ip))) {
-                return ImmutableSet.of(H2);
-            } else if ((DUAL_HOME_H.ipAddresses().contains(ip))) {
-                return ImmutableSet.of(DUAL_HOME_H);
-            }
-            return ImmutableSet.of();
-        }
-    }
-
-    private class TestLinkService extends LinkNib {
-        @Override
-        public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
-            if (connectPoint.equals(TOPO_FLOW_1_OUT_CP)
-                    || connectPoint.equals(TOPO_FLOW_OUT_CP_1)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(connectPoint)
-                        .dst(TOPO_FLOW_2_IN_CP)
-                        .build());
-            } else if (connectPoint.equals(TOPO_FLOW_2_OUT_CP)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(TOPO_FLOW_2_OUT_CP)
-                        .dst(TOPO_FLOW_3_IN_CP)
-                        .build());
-            } else if (connectPoint.equals(TOPO_FLOW_OUT_CP_2)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(TOPO_FLOW_OUT_CP_2)
-                        .dst(TOPO_FLOW_4_IN_CP)
-                        .build());
-            } else if (connectPoint.equals(TOPO_FLOW_4_OUT_CP)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(TOPO_FLOW_4_OUT_CP)
-                        .dst(TOPO_FLOW_3_IN_2_CP)
-                        .build());
-            } else if (connectPoint.equals(DUAL_LINK_1_CP_2_OUT)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(DUAL_LINK_1_CP_2_OUT)
-                        .dst(DUAL_LINK_2_CP_1_IN)
-                        .build());
-            } else if (connectPoint.equals(DUAL_LINK_1_CP_3_OUT)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(DUAL_LINK_1_CP_3_OUT)
-                        .dst(DUAL_LINK_2_CP_4_IN)
-                        .build());
-            } else if (connectPoint.equals(DUAL_LINK_2_CP_2_OUT)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(DUAL_LINK_2_CP_2_OUT)
-                        .dst(DUAL_LINK_3_CP_1_IN)
-                        .build());
-            } else if (connectPoint.equals(DUAL_LINK_2_CP_3_OUT)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(DUAL_LINK_2_CP_3_OUT)
-                        .dst(DUAL_LINK_3_CP_2_IN)
-                        .build());
-            } else if (connectPoint.equals(DUAL_HOME_CP_1_2)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(DUAL_HOME_CP_1_2)
-                        .dst(DUAL_HOME_CP_2_1)
-                        .build());
-            } else if (connectPoint.equals(DUAL_HOME_CP_1_3)) {
-                return ImmutableSet.of(DefaultLink.builder()
-                        .providerId(ProviderId.NONE)
-                        .type(Link.Type.DIRECT)
-                        .src(DUAL_HOME_CP_1_3)
-                        .dst(DUAL_HOME_CP_3_1)
-                        .build());
-            }
-            return ImmutableSet.of();
-        }
-    }
-
-    private class TestDeviceService extends DeviceNib {
-        @Override
-        public Device getDevice(DeviceId deviceId) {
-            if (deviceId.equals(DeviceId.deviceId("nonexistent"))) {
-                return null;
-            }
-            return new DefaultDevice(ProviderId.NONE, DeviceId.deviceId("test"), SWITCH,
-                    "test", "test", "test", "test", new ChassisId(),
-                    DefaultAnnotations.builder().set("foo", "bar").build());
-        }
-
-        @Override
-        public Port getPort(ConnectPoint cp) {
-            return new DefaultPort(null, cp.port(), true, DefaultAnnotations.builder().build());
-        }
-
-        @Override
-        public boolean isAvailable(DeviceId deviceId) {
-            return !deviceId.equals(OFFLINE_DEVICE);
-        }
-    }
-
-    private class TestDriverService extends DriverNib {
-        @Override
-        public String getDriverName(DeviceId deviceId) {
-            if (deviceId.equals(HARDWARE_DEVICE) || deviceId.equals(HARDWARE_DEVICE_10)) {
-                return "ofdpa";
-            }
-            return "NotHWDriver";
-        }
-    }
-
-    private class TestMastershipService extends MastershipNib {
-        @Override
-        public NodeId getMasterFor(DeviceId deviceId) {
-            return NodeId.nodeId(MASTER_1);
-        }
-    }
-
-    private class TestEdgePortService extends EdgePortNib {
-        @Override
-        public boolean isEdgePoint(ConnectPoint point) {
-            return point.equals(MULTICAST_OUT_CP) ||
-                    point.equals(MULTICAST_OUT_CP_2);
-        }
-    }
-
-    private class TestRouteService extends RouteNib {
-        @Override
-        public Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip) {
-            return Optional.empty();
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootUtilsTest.java b/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootUtilsTest.java
deleted file mode 100644
index c8195c0..0000000
--- a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootUtilsTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2018-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.t3.impl;
-
-import org.junit.Test;
-import org.onlab.packet.MacAddress;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test for util methods of the Trellis Troubleshoot Toolkit.
- */
-public class TroubleshootUtilsTest {
-
-    @Test
-    public void testMacMatch() {
-
-        MacAddress min = MacAddress.valueOf("01:00:5E:00:00:00");
-        MacAddress mask = MacAddress.valueOf("FF:FF:FF:80:00:00");
-        MacAddress macOk = MacAddress.valueOf("01:00:5E:00:00:01");
-
-        assertTrue("False on correct match", TroubleshootUtils.compareMac(macOk, min, mask));
-
-        MacAddress macWrong = MacAddress.valueOf("01:00:5E:80:00:00");
-
-        assertFalse("True on false match", TroubleshootUtils.compareMac(macWrong, min, mask));
-
-        MacAddress maskEmpty = MacAddress.valueOf("00:00:00:00:00:00");
-
-        assertTrue("False on empty Mask", TroubleshootUtils.compareMac(macOk, min, maskEmpty));
-
-        MacAddress maskFull = MacAddress.valueOf("FF:FF:FF:FF:FF:FF");
-
-        assertFalse("True on full Mask", TroubleshootUtils.compareMac(macOk, min, maskFull));
-
-    }
-}
\ No newline at end of file
diff --git a/apps/t3/web/BUILD b/apps/t3/web/BUILD
deleted file mode 100644
index 0fd733f..0000000
--- a/apps/t3/web/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + KRYO + JACKSON + REST + CLI + [
-    "@jersey_server//jar",
-    "//apps/t3/app:onos-apps-t3-app",
-]
-
-osgi_jar(
-    api_description = "REST API for T3",
-    api_package = "org.onosproject.t3.rest",
-    api_title = "T3 REST API",
-    api_version = "1.0",
-    web_context = "/onos/v1/t3",
-    deps = COMPILE_DEPS,
-)
diff --git a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebApplication.java b/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebApplication.java
deleted file mode 100644
index 5f6a548..0000000
--- a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2018-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.t3.rest;
-
-
-import org.onlab.rest.AbstractWebApplication;
-
-import java.util.Set;
-
-public class T3WebApplication extends AbstractWebApplication {
-    @Override
-    public Set<Class<?>> getClasses() {
-        return getClasses(T3WebResource.class);
-    }
-
-}
diff --git a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebResource.java b/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebResource.java
deleted file mode 100644
index 275be8c..0000000
--- a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebResource.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright 2018-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.t3.rest;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.HostId;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.group.Group;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.t3.api.GroupsInDevice;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.slf4j.Logger;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Trellis Troubleshooting Tool REST API.
- */
-@Path("t3")
-public class T3WebResource extends AbstractWebResource {
-    private final ObjectMapper mapper = new ObjectMapper();
-    private static final Logger LOG = getLogger(T3WebResource.class);
-
-    /**
-     * Returns the trace non verbose result for the given source and destination ips.
-     *
-     * @param srcHost source ip identifier
-     * @param dstHost destination ip identifier
-     * @param ethType ethernet type identifier
-     * @return 200 OK with component properties of given component and variable
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("simple/{srcHost}/{dstHost}/{ethType}")
-    public Response getT3Simple(@PathParam("srcHost") String srcHost, @PathParam("dstHost") String dstHost,
-                                @PathParam("ethType") String ethType) {
-
-        ObjectNode node;
-        try {
-            node = getT3JsonOutput(srcHost, dstHost, ethType, false);
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException(e);
-        }
-        return Response.status(200).entity(node).build();
-
-    }
-
-    /**
-     * Returns the trace verbose result for the given source and destination ips.
-     *
-     * @param srcHost source ip identifier
-     * @param dstHost destination ip identifier
-     * @param ethType ethernet type identifier
-     * @return 200 OK with component properties of given component and variable
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("simple/{srcHost}/{dstHost}/{ethType}/verbose")
-    public Response getT3SimpleVerbose(@PathParam("srcHost") String srcHost, @PathParam("dstHost") String dstHost,
-                                       @PathParam("ethType") String ethType) {
-
-        ObjectNode node;
-        try {
-            node = getT3JsonOutput(srcHost, dstHost, ethType, true);
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException(e);
-        }
-        return Response.status(200).entity(node).build();
-    }
-
-    /**
-     * Returns the mcast trace non verbose result.
-     *
-     * @return 200 OK
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("mcast")
-    public Response getT3Mcast() {
-        ObjectNode node = null;
-        try {
-            node = getT3McastJsonOutput(false);
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException(e);
-        }
-        return Response.status(200).entity(node).build();
-    }
-
-    /**
-     * Returns the mcast trace verbose result.
-     *
-     * @return 200 OK
-     */
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("mcast/verbose")
-    public Response getT3McastVerbose() {
-        ObjectNode node;
-        try {
-            node = getT3McastJsonOutput(true);
-
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException(e);
-        }
-        return Response.status(200).entity(node).build();
-    }
-
-    /**
-     * Returns trace verbose or non verbose json output for the given trace.
-     *
-     * @param verbose based on verbosity level
-     * @return a json representing the trace.
-     */
-    private ObjectNode getT3McastJsonOutput(boolean verbose) {
-        TroubleshootService troubleshootService = get(TroubleshootService.class);
-        final ObjectNode nodeOutput = mapper.createObjectNode();
-        nodeOutput.put("title", "Tracing all Multicast routes in the System");
-
-        //Create the generator for the list of traces.
-        List<Set<StaticPacketTrace>> generator = troubleshootService.getMulitcastTrace(VlanId.vlanId("None"));
-        int totalTraces = 0;
-        List<StaticPacketTrace> failedTraces = new ArrayList<>();
-        StaticPacketTrace previousTrace = null;
-        ArrayNode traceArray = mapper.createArrayNode();
-        for (Set<StaticPacketTrace> traces : generator) {
-            ObjectNode genNode = mapper.createObjectNode();
-            totalTraces++;
-            //Print also Route if possible or packet
-            ArrayNode traceOutput = mapper.createArrayNode();
-            if (verbose) {
-                traces.forEach(trace -> {
-                    ObjectNode traceObj = mapper.createObjectNode();
-                    ArrayNode node = mapper.createArrayNode();
-                    for (Criterion packet : trace.getInitialPacket().criteria()) {
-                        node.add(packet.toString());
-                    }
-                    traceObj.set("input packet", node);
-                    traceObj.set("trace", getTraceJson(trace, verbose));
-                    traceOutput.add(traceObj);
-                });
-            } else {
-                for (StaticPacketTrace trace : traces) {
-                    ObjectNode traceObject = mapper.createObjectNode();
-                    traceObject.set("trace", traceNode(previousTrace, trace));
-                    if (previousTrace == null || !previousTrace.equals(trace)) {
-                        previousTrace = trace;
-                    }
-                    traceObject.put("result", trace.isSuccess());
-                    if (!trace.isSuccess()) {
-                        traceObject.put("reason", trace.resultMessage());
-                        failedTraces.add(trace);
-                    }
-                    traceOutput.add(traceObject);
-                }
-            }
-            genNode.set("traces", traceOutput);
-            traceArray.add(genNode);
-        }
-        nodeOutput.set("tracing packet", traceArray);
-
-        if (!verbose) {
-            if (failedTraces.size() != 0) {
-                nodeOutput.put("failed traces", failedTraces.size());
-            }
-            previousTrace = null;
-            for (StaticPacketTrace trace : failedTraces) {
-                if (previousTrace == null || !previousTrace.equals(trace)) {
-                    previousTrace = trace;
-                }
-                nodeOutput.set("trace", traceNode(previousTrace, trace));
-                if (trace != null) {
-                    nodeOutput.put("failure", trace.resultMessage());
-                }
-            }
-            nodeOutput.put("total traces", totalTraces);
-            nodeOutput.put("errors", failedTraces.size());
-        }
-        return nodeOutput;
-    }
-
-    /**
-     * Returns verbose or non verbose json output for the given trace.      *
-     *
-     * @param previousTrace the trace
-     * @param trace         based on verbosity level
-     * @return a json representing the trace.
-     */
-    private ObjectNode traceNode(StaticPacketTrace previousTrace, StaticPacketTrace trace) {
-        ObjectNode obj = mapper.createObjectNode();
-        if (previousTrace == null || !previousTrace.equals(trace)) {
-            previousTrace = trace;
-            ConnectPoint initialConnectPoint = trace.getInitialConnectPoint();
-            TrafficSelector initialPacket = trace.getInitialPacket();
-            boolean isIPv4 = ((EthTypeCriterion) initialPacket.getCriterion(Criterion.Type.ETH_TYPE))
-                    .ethType().equals(EthType.EtherType.IPV4.ethType()
-                    );
-            IpPrefix group = ((IPCriterion) (isIPv4 ? trace.getInitialPacket()
-                    .getCriterion(Criterion.Type.IPV4_DST) : trace.getInitialPacket()
-                    .getCriterion(Criterion.Type.IPV6_DST))).ip();
-            obj.put("source", initialConnectPoint.toString());
-            obj.put("group", group.toString());
-        }
-        ArrayNode nodePath = mapper.createArrayNode();
-        for (List<ConnectPoint> listPaths : trace.getCompletePaths()) {
-            nodePath.add(listPaths.get(listPaths.size() - 1).toString());
-        }
-        if (trace.getCompletePaths().size() > 1) {
-            obj.set("sinks", nodePath);
-        } else {
-            obj.set("sink", nodePath);
-        }
-        return obj;
-    }
-
-    /**
-     * Returns trace verbose or non verbose json output for the given trace.
-     *
-     * @param srcHost source ip identifier
-     * @param dstHost destination ip identifier
-     * @param ethType the ethernet Type
-     * @param verbose based on verbosity level
-     * @return a json representing the trace.
-     */
-    private ObjectNode getT3JsonOutput(String srcHost, String dstHost, String ethType, Boolean verbose) {
-        TroubleshootService troubleshootService = get(TroubleshootService.class);
-        final ObjectNode nodeOutput = mapper.createObjectNode();
-        //Tracing between host ips
-        ArrayNode ipList = mapper.createArrayNode();
-        ipList.add(srcHost);
-        ipList.add(dstHost);
-        nodeOutput.set("hostIps ", ipList);
-        EthType.EtherType type = EthType.EtherType.valueOf(ethType.toUpperCase());
-
-        //Build the traces
-        Set<StaticPacketTrace> traces = troubleshootService.trace(HostId.hostId(srcHost), HostId.hostId(dstHost), type);
-        traces.forEach(trace -> {
-
-            if (trace.getInitialPacket() != null) {
-                ArrayNode node = mapper.createArrayNode();
-                for (Criterion packet : trace.getInitialPacket().criteria()) {
-                    node.add(packet.toString());
-                }
-                nodeOutput.set("input packet", node);
-                nodeOutput.set("trace", getTraceJson(trace, verbose));
-            } else {
-                LOG.debug("cannot obtain trace between: ", srcHost, dstHost);
-                nodeOutput.set("failed trace", ipList);
-                nodeOutput.put("reason", trace.resultMessage());
-            }
-        });
-        return nodeOutput;
-    }
-
-    /**
-     * Returns verbose or non verbose json output for the given trace.      *
-     *
-     * @param trace     the trace
-     * @param verbosity based on verbosity level
-     * @return a json representing the trace.
-     */
-    public ObjectNode getTraceJson(StaticPacketTrace trace, boolean verbosity) {
-        ObjectNode nodeOutput = mapper.createObjectNode();
-        if (verbosity) {
-            nodeOutput.set("trace", getTrace(trace, verbosity));
-        } else {
-            ArrayNode nodePath = mapper.createArrayNode();
-            for (List<ConnectPoint> listPaths : trace.getCompletePaths()) {
-                ArrayNode node = mapper.createArrayNode();
-                for (ConnectPoint path : listPaths) {
-                    node.add(path.toString());
-                }
-                nodePath.add(node);
-            }
-            nodeOutput.set("paths", nodePath);
-        }
-
-        nodeOutput.put("result", trace.resultMessage());
-        return nodeOutput;
-    }
-
-    /**
-     * Returns verbose json output for the given trace.      *
-     *
-     * @param trace the trace
-     * @return a json representing the trace.
-     */
-    private ObjectNode getTrace(StaticPacketTrace trace, boolean verbose) {
-
-        ObjectNode nodeOutput = mapper.createObjectNode();
-
-        List<List<ConnectPoint>> paths = trace.getCompletePaths();
-        ArrayNode nodePath = mapper.createArrayNode();
-        for (List<ConnectPoint> path : paths) {
-            ArrayNode pathNode = mapper.createArrayNode();
-            for (ConnectPoint pathItr : path) {
-                pathNode.add(pathItr.toString());
-            }
-            nodePath.add(pathNode);
-
-            ConnectPoint previous = null;
-
-            if (path.size() == 1) {
-                ConnectPoint connectPoint = path.get(0);
-                nodeOutput.put("device", connectPoint.deviceId().toString());
-                nodeOutput.put("input", connectPoint.toString());
-                nodeOutput.put("flowCount", trace.getFlowsForDevice(connectPoint.deviceId()).size());
-                nodeOutput.set("flows", getFlowArray(trace, connectPoint, verbose));
-
-                List<GroupsInDevice> groupsInDevice = trace.getGroupOuputs(connectPoint.deviceId());
-
-                if (groupsInDevice != null) {
-                    groupsInDevice.forEach(output -> {
-                        nodeOutput.set("groups", getGroupObj(connectPoint, output, verbose));
-                    });
-                }
-
-            } else {
-                for (ConnectPoint connectPoint : path) {
-                    if (previous == null || !previous.deviceId().equals(connectPoint.deviceId())) {
-                        nodeOutput.put("device", connectPoint.deviceId().toString());
-                        nodeOutput.put("input", connectPoint.toString());
-                        nodeOutput.put("flows", trace.getFlowsForDevice(connectPoint.deviceId()).size());
-                        nodeOutput.put("verbose", verbose);
-                        nodeOutput.set("flows", getFlowArray(trace, connectPoint, verbose));
-                    } else {
-                        List<GroupsInDevice> groupsInDevice = trace.getGroupOuputs(connectPoint.deviceId());
-                        if (groupsInDevice != null) {
-                            groupsInDevice.forEach(output -> {
-                                nodeOutput.set("groups", getGroupObj(connectPoint, output, verbose));
-                            });
-
-                        }
-
-                    }
-                    previous = connectPoint;
-                }
-            }
-        }
-        nodeOutput.set("path", nodePath);
-        return nodeOutput;
-    }
-
-    //Return groups Object for a given trace and a specified level of verbosity
-    private ObjectNode getGroupObj(ConnectPoint connectPoint, GroupsInDevice output, boolean verbose) {
-        ArrayNode groupArray = mapper.createArrayNode();
-        ObjectNode groupsObj = mapper.createObjectNode();
-        if (output.getOutput().equals(connectPoint)) {
-            output.getGroups().forEach(group -> {
-                ObjectNode groups = mapper.createObjectNode();
-                if (verbose) {
-                    groups = codec(Group.class).encode(group, this);
-                } else {
-                    groups.put("groupId", group.id().toString());
-                }
-                groupArray.add(groups);
-            });
-            ArrayNode node = mapper.createArrayNode();
-            for (Criterion packet : output.getFinalPacket().criteria()) {
-                node.add(packet.toString());
-            }
-            groupsObj.set("outgoing packet", node);
-        }
-        groupsObj.set("groups", groupArray);
-        return groupsObj;
-    }
-
-    //Return flows Object for a given trace and a specified level of verbosity
-    private ArrayNode getFlowArray(StaticPacketTrace trace, ConnectPoint connectPoint, boolean verbose) {
-        ArrayNode flowArray = mapper.createArrayNode();
-        trace.getFlowsForDevice(connectPoint.deviceId()).forEach(f -> {
-            ObjectNode flows = mapper.createObjectNode();
-            if (verbose) {
-                flows = codec(FlowEntry.class).encode(f, this);
-            } else {
-                flows.put("flowId: ", f.id().toString());
-                flows.put("table: ", f.table().toString());
-                flows.put("selector: ", f.selector().criteria().toString());
-            }
-            flowArray.add(flows);
-        });
-        return flowArray;
-    }
-
-}
diff --git a/apps/t3/web/src/main/java/org/onosproject/t3/rest/package-info.java b/apps/t3/web/src/main/java/org/onosproject/t3/rest/package-info.java
deleted file mode 100644
index e390f3e..0000000
--- a/apps/t3/web/src/main/java/org/onosproject/t3/rest/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-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.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics implementation.
- */
-package org.onosproject.t3.rest;
diff --git a/apps/t3/web/src/main/webapp/WEB-INF/web.xml b/apps/t3/web/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 9bed969..0000000
--- a/apps/t3/web/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Copyright 2018-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.
-  -->
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://java.sun.com/xml/ns/javaee"
-         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-         id="ONOS" version="2.5">
-    <display-name>T3 REST API v1.0</display-name>
-
-    <security-constraint>
-        <web-resource-collection>
-            <web-resource-name>Secured</web-resource-name>
-            <url-pattern>/*</url-pattern>
-        </web-resource-collection>
-        <auth-constraint>
-            <role-name>admin</role-name>
-            <role-name>viewer</role-name>
-        </auth-constraint>
-    </security-constraint>
-
-    <security-role>
-        <role-name>admin</role-name>
-        <role-name>viewer</role-name>
-    </security-role>
-
-    <login-config>
-        <auth-method>BASIC</auth-method>
-        <realm-name>karaf</realm-name>
-    </login-config>
-
-    <servlet>
-        <servlet-name>JAX-RS Service</servlet-name>
-        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
-        <init-param>
-            <param-name>javax.ws.rs.Application</param-name>
-            <param-value>org.onosproject.t3.rest.T3WebApplication</param-value>
-        </init-param>
-        <load-on-startup>1</load-on-startup>
-    </servlet>
-
-    <servlet-mapping>
-        <servlet-name>JAX-RS Service</servlet-name>
-        <url-pattern>/*</url-pattern>
-    </servlet-mapping>
-</web-app>
diff --git a/tools/build/bazel/modules.bzl b/tools/build/bazel/modules.bzl
index c1c3e0a..e9386db 100644
--- a/tools/build/bazel/modules.bzl
+++ b/tools/build/bazel/modules.bzl
@@ -289,9 +289,7 @@
     "//apps/routing/fpm:onos-apps-routing-fpm-oar": [],
     "//apps/scalablegateway:onos-apps-scalablegateway-oar": [],
     "//apps/sdnip:onos-apps-sdnip-oar": [],
-    "//apps/segmentrouting:onos-apps-segmentrouting-oar": ["seba"],
     "//apps/simplefabric:onos-apps-simplefabric-oar": [],
-    "//apps/t3:onos-apps-t3-oar": [],
     # "//apps/tenbi:onos-apps-tenbi-oar": [],
     # "//apps/tenbi/yangmodel:onos-apps-tenbi-yangmodel-feature": [],
     "//apps/test/cluster-ha:onos-apps-test-cluster-ha-oar": [],
