diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
index 76c8d56e66f6bd75fcc2b0c0cf202fb4b2ae2808..be6c98e90764058424cf8ae8c819131fbe8d5862 100644
--- a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
+++ b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
@@ -45,7 +45,7 @@ public interface IRoutingService extends IFloodlightService {
         }
     };
 
-    public PATH_METRIC setPathMetric(PATH_METRIC metric);
+    public void setPathMetric(PATH_METRIC metric);
     public PATH_METRIC getPathMetric();
 
     /**
@@ -76,7 +76,7 @@ public interface IRoutingService extends IFloodlightService {
      * @param dstPort destination port on destination switch
      * @return the lowest cost path
      */
-    public Route getPath(DatapathId srcId, OFPort srcPort, DatapathId dstId, OFPort dstPort);
+    public Route getPath(DatapathId src, OFPort srcPort, DatapathId dst, OFPort dstPort);
 
     /**
      * Return all possible paths up to quantity of the globally configured max.
@@ -123,7 +123,7 @@ public interface IRoutingService extends IFloodlightService {
      * @param numReqPaths the requested quantity of paths
      * @return list of paths ordered least to greatest cost
      */
-    public List<Route> getPathsSlow(DatapathId srcDpid, DatapathId dstDpid, int numReqPaths);
+    public List<Route> getPathsSlow(DatapathId src, DatapathId dst, int numReqPaths);
 
     /** 
      * Check if a path exists between src and dst
diff --git a/src/main/java/net/floodlightcontroller/routing/RoutingManager.java b/src/main/java/net/floodlightcontroller/routing/RoutingManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5d8c42c6f98f8e417d104ed3b3cccbcbb2cd7ac
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/routing/RoutingManager.java
@@ -0,0 +1,110 @@
+package net.floodlightcontroller.routing;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.topology.ITopologyManagerBackend;
+import net.floodlightcontroller.topology.ITopologyService;
+
+/**
+ * Separate path-finding and routing functionality from the 
+ * topology package. It makes sense to keep much of the core
+ * code in the TopologyInstance, but the TopologyManger is
+ * too confusing implementing so many interfaces and doing
+ * so many tasks. This is a cleaner approach IMHO.
+ * 
+ * @author rizard
+ */
+public class RoutingManager implements IFloodlightModule, IRoutingService {
+    private Logger log = LoggerFactory.getLogger(RoutingManager.class);
+    
+    private static ITopologyManagerBackend tm;
+    
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+        return ImmutableSet.of(IRoutingService.class);
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+        return ImmutableMap.of(IRoutingService.class, this);
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+        return ImmutableSet.of(ITopologyService.class);
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context) throws FloodlightModuleException {
+        log.debug("RoutingManager starting up");
+        tm = (ITopologyManagerBackend) context.getServiceImpl(ITopologyService.class);
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { }
+
+    @Override
+    public void setPathMetric(PATH_METRIC metric) {
+        tm.setPathMetric(metric);
+    }
+
+    @Override
+    public PATH_METRIC getPathMetric() {
+        return tm.getPathMetric();
+    }
+
+
+    @Override
+    public void setMaxPathsToCompute(int max) {
+        tm.setMaxPathsToCompute(max);
+    }
+
+    @Override
+    public int getMaxPathsToCompute() {
+        return tm.getMaxPathsToCompute();
+    }
+
+    @Override
+    public Route getPath(DatapathId src, DatapathId dst) {
+        return tm.getCurrentTopologyInstance().getPath(src, dst);
+    }
+
+    @Override
+    public Route getPath(DatapathId src, OFPort srcPort, DatapathId dst, OFPort dstPort) {
+        return tm.getCurrentTopologyInstance().getPath(src, srcPort, dst, dstPort);
+    }
+
+    @Override
+    public List<Route> getPathsFast(DatapathId src, DatapathId dst) {
+        return tm.getCurrentTopologyInstance().getPathsFast(src, dst, tm.getMaxPathsToCompute());
+    }
+
+    @Override
+    public List<Route> getPathsFast(DatapathId src, DatapathId dst, int numReqPaths) {
+        return tm.getCurrentTopologyInstance().getPathsFast(src, dst, numReqPaths);
+    }
+
+    @Override
+    public List<Route> getPathsSlow(DatapathId src, DatapathId dst, int numReqPaths) {
+        return tm.getCurrentTopologyInstance().getPathsSlow(src, dst, numReqPaths);
+    }
+
+    @Override
+    public boolean pathExists(DatapathId src, DatapathId dst) {
+        return tm.getCurrentTopologyInstance().pathExists(src, dst);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/routing/web/PathMetricsResource.java b/src/main/java/net/floodlightcontroller/routing/web/PathMetricsResource.java
index 73fe3f7542d0a6b8c3ddd08fad2b8968779fa44b..cf032a135520f0395eefa7a405409f673af901d8 100644
--- a/src/main/java/net/floodlightcontroller/routing/web/PathMetricsResource.java
+++ b/src/main/java/net/floodlightcontroller/routing/web/PathMetricsResource.java
@@ -63,12 +63,8 @@ public class PathMetricsResource extends ServerResource {
                 return Collections.singletonMap("error", "invalid path metric " + metric);
         }
 
-        if (routing.setPathMetric(type) != type) {
-            log.error("Failed to set valid path metric {}. Bug?", type.getMetricName());
-            return Collections.singletonMap("error", "failed to set valid path metric " + type.getMetricName());
-        }
-
-        log.debug("Set path metric to {}", type.getMetricName());
+        log.debug("Setting path metric to {}", type.getMetricName());
+        routing.setPathMetric(type);
         return Collections.singletonMap("success", "path metric set to " + type.getMetricName());
     }
 }
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyManagerBackend.java b/src/main/java/net/floodlightcontroller/topology/ITopologyManagerBackend.java
new file mode 100644
index 0000000000000000000000000000000000000000..64c4e06a2abcf3581fa23e5a99a96503d92d727d
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/topology/ITopologyManagerBackend.java
@@ -0,0 +1,13 @@
+package net.floodlightcontroller.topology;
+
+import net.floodlightcontroller.routing.IRoutingService.PATH_METRIC;
+
+public interface ITopologyManagerBackend {
+    public TopologyInstance getCurrentTopologyInstance();
+    
+    public PATH_METRIC getPathMetric();
+    public void setPathMetric(PATH_METRIC metric);
+    
+    public int getMaxPathsToCompute();
+    public void setMaxPathsToCompute(int max);
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
index 318ba23523beaa0c70507effd0c9374516e81fd2..d3f50f404f74a89d822ab6ce20c022d7f4b3b945 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
@@ -80,7 +80,7 @@ public class TopologyInstance {
     private Map<DatapathId, Set<NodePortTuple>> portsBroadcastPerArchipelago;
     private Map<RouteId, List<Route>>           pathcache; /* contains computed paths ordered best to worst */
 
-    protected TopologyInstance(Map<DatapathId, Set<OFPort>> portsWithLinks,
+    public TopologyInstance(Map<DatapathId, Set<OFPort>> portsWithLinks,
             Set<NodePortTuple> portsBlocked,
             Map<NodePortTuple, Set<Link>> linksNonBcastNonTunnel,
             Set<NodePortTuple> portsWithMoreThanTwoLinks,
@@ -138,7 +138,7 @@ public class TopologyInstance {
         this.archipelagoFromCluster = new HashMap<Cluster, Archipelago>();
     }
 
-    protected void compute() {
+    public void compute() {
         /*
          * Step 1: Compute clusters ignoring ports with > 2 links and 
          * blocked links.
@@ -185,7 +185,7 @@ public class TopologyInstance {
     /*
      * Checks if OF port is edge port
      */
-    protected boolean isEdge(DatapathId sw, OFPort portId) { 
+    public boolean isEdge(DatapathId sw, OFPort portId) { 
         NodePortTuple np = new NodePortTuple(sw, portId);
         if (links.get(np) == null || links.get(np).isEmpty()) {
             return true;
@@ -198,7 +198,7 @@ public class TopologyInstance {
     /*
      * Returns broadcast ports for the given DatapathId
      */
-    protected Set<OFPort> swBroadcastPorts(DatapathId sw) {
+    public Set<OFPort> swBroadcastPorts(DatapathId sw) {
         if (!portsBroadcastPerSwitch.containsKey(sw) || portsBroadcastPerSwitch.get(sw) == null) {
             log.debug("Could not locate broadcast ports for switch {}", sw);
             return Collections.emptySet();
@@ -402,11 +402,11 @@ public class TopologyInstance {
         return currIndex;
     }
 
-    protected Set<NodePortTuple> getBlockedPorts() {
+    public Set<NodePortTuple> getBlockedPorts() {
         return this.portsBlocked;
     }
 
-    protected Set<Link> getBlockedLinks() {
+    public Set<Link> getBlockedLinks() {
         return this.linksBlocked;
     }
 
@@ -415,33 +415,33 @@ public class TopologyInstance {
      * @param l
      * @return
      */
-    protected boolean isBlockedLink(Link l) {
+    public boolean isBlockedLink(Link l) {
         NodePortTuple n1 = new NodePortTuple(l.getSrc(), l.getSrcPort());
         NodePortTuple n2 = new NodePortTuple(l.getDst(), l.getDstPort());
         return (isBlockedPort(n1) || isBlockedPort(n2));
     }
 
-    protected boolean isBlockedPort(NodePortTuple npt) {
+    public boolean isBlockedPort(NodePortTuple npt) {
         return portsBlocked.contains(npt);
     }
 
-    protected boolean isTunnelPort(NodePortTuple npt) {
+    public boolean isTunnelPort(NodePortTuple npt) {
         return portsTunnel.contains(npt);
     }
 
-    protected boolean isTunnelLink(Link l) {
+    public boolean isTunnelLink(Link l) {
         NodePortTuple n1 = new NodePortTuple(l.getSrc(), l.getSrcPort());
         NodePortTuple n2 = new NodePortTuple(l.getDst(), l.getDstPort());
         return (isTunnelPort(n1) || isTunnelPort(n2));
     }
 
-    protected boolean isBroadcastLink(Link l) {
+    public boolean isBroadcastLink(Link l) {
         NodePortTuple n1 = new NodePortTuple(l.getSrc(), l.getSrcPort());
         NodePortTuple n2 = new NodePortTuple(l.getDst(), l.getDstPort());
         return (isBroadcastPort(n1) || isBroadcastPort(n2));
     }
 
-    protected boolean isBroadcastPort(NodePortTuple npt) {
+    public boolean isBroadcastPort(NodePortTuple npt) {
         return portsBroadcastAll.contains(npt);
     }
 
@@ -647,7 +647,7 @@ public class TopologyInstance {
     /*
      * Creates a map of links and the cost associated with each link
      */
-    protected Map<Link,Integer> initLinkCostMap() {
+    public Map<Link,Integer> initLinkCostMap() {
         Map<Link, Integer> linkCost = new HashMap<Link, Integer>();
         long rawLinkSpeed;
         int linkSpeedMBps;
@@ -821,7 +821,7 @@ public class TopologyInstance {
      * Getter Functions
      */
 
-    protected boolean pathExists(DatapathId srcId, DatapathId dstId) {
+    public boolean pathExists(DatapathId srcId, DatapathId dstId) {
         Archipelago srcA = getArchipelago(srcId);
         Archipelago dstA = getArchipelago(dstId);
         if (!srcA.getId().equals(dstA.getId())) {
@@ -876,7 +876,7 @@ public class TopologyInstance {
      * @param k: The number of routes that you want. Must be positive integer.
      * @return ArrayList of Routes or null if bad parameters
      */
-    protected List<Route> getPathsFast(DatapathId src, DatapathId dst, int k) {
+    public List<Route> getPathsFast(DatapathId src, DatapathId dst, int k) {
         RouteId routeId = new RouteId(src, dst);
         List<Route> routes = pathcache.get(routeId);
 
@@ -903,7 +903,7 @@ public class TopologyInstance {
      * @param k: The number of routes that you want. Must be positive integer.
      * @return ArrayList of Routes or null if bad parameters
      */
-    protected List<Route> getPathsSlow(DatapathId src, DatapathId dst, int k) {
+    public List<Route> getPathsSlow(DatapathId src, DatapathId dst, int k) {
         RouteId routeId = new RouteId(src, dst);
         List<Route> routes = pathcache.get(routeId);
 
@@ -926,7 +926,7 @@ public class TopologyInstance {
         return null;
     }
 
-    protected void setPathCosts(Route r) {
+    public void setPathCosts(Route r) {
         U64 cost = U64.ZERO;
 
         // Set number of hops. Assuming the list of NPTs is always even.
@@ -1169,7 +1169,7 @@ public class TopologyInstance {
      * @param dstPort
      * @return
      */
-    protected Route getPath(DatapathId srcId, OFPort srcPort,
+    public Route getPath(DatapathId srcId, OFPort srcPort,
             DatapathId dstId, OFPort dstPort) {
         // Return null if the route source and destination are the
         // same switch ports.
@@ -1207,7 +1207,7 @@ public class TopologyInstance {
      * @return
      */
 
-    protected Route getPath(DatapathId srcId, DatapathId dstId) {
+    public Route getPath(DatapathId srcId, DatapathId dstId) {
         // Return null route if srcId equals dstId
         if (srcId.equals(dstId)) return null;
 
@@ -1232,7 +1232,7 @@ public class TopologyInstance {
     //  ITopologyService interface method helpers.
     //
 
-    protected boolean isInternalLinkInCluster(DatapathId switchid, OFPort port) {
+    public boolean isInternalLinkInCluster(DatapathId switchid, OFPort port) {
         return !isAttachmentPointPort(switchid, port);
     }
 
@@ -1244,7 +1244,7 @@ public class TopologyInstance {
         return true;
     }
 
-    protected DatapathId getClusterId(DatapathId switchId) {
+    public DatapathId getClusterId(DatapathId switchId) {
         Cluster c = clustersPerSwitch.get(switchId);
         if (c != null) { 
             return c.getId();
@@ -1252,7 +1252,7 @@ public class TopologyInstance {
         return switchId;
     }
 
-    protected DatapathId getArchipelagoId(DatapathId switchId) {
+    public DatapathId getArchipelagoId(DatapathId switchId) {
         Cluster c = clustersPerSwitch.get(switchId);
         if (c != null) {
             return archipelagoFromCluster.get(c).getId();
@@ -1260,7 +1260,7 @@ public class TopologyInstance {
         return switchId;
     }
 
-    protected Set<DatapathId> getSwitchesInCluster(DatapathId switchId) {
+    public Set<DatapathId> getSwitchesInCluster(DatapathId switchId) {
         Cluster c = clustersPerSwitch.get(switchId);
         if (c != null) {
             return c.getNodes();
@@ -1269,7 +1269,7 @@ public class TopologyInstance {
         return ImmutableSet.of(switchId);
     }
 
-    protected boolean isInSameCluster(DatapathId switch1, DatapathId switch2) {
+    public boolean isInSameCluster(DatapathId switch1, DatapathId switch2) {
         Cluster c1 = clustersPerSwitch.get(switch1);
         Cluster c2 = clustersPerSwitch.get(switch2);
         if (c1 != null && c2 != null) {
@@ -1278,14 +1278,14 @@ public class TopologyInstance {
         return (switch1.equals(switch2));
     }
 
-    protected boolean isNotBlocked(DatapathId sw, OFPort portId) {
+    public boolean isNotBlocked(DatapathId sw, OFPort portId) {
         return !isBlockedPort(new NodePortTuple(sw, portId));
     }
 
     /*
      * Takes finiteBroadcastTree into account to prevent loops in the network
      */
-    protected boolean isBroadcastAllowedOnSwitchPort(DatapathId sw, OFPort portId) {
+    public boolean isBroadcastAllowedOnSwitchPort(DatapathId sw, OFPort portId) {
         if (!isEdge(sw, portId)){       
             NodePortTuple npt = new NodePortTuple(sw, portId);
             if (portsBroadcastAll.contains(npt))
@@ -1295,12 +1295,12 @@ public class TopologyInstance {
         return true;
     }
 
-    protected boolean isConsistent(DatapathId oldSw, OFPort oldPort, DatapathId newSw, OFPort newPort) {
+    public boolean isConsistent(DatapathId oldSw, OFPort oldPort, DatapathId newSw, OFPort newPort) {
         if (isInternalLinkInCluster(newSw, newPort)) return true;
         return (oldSw.equals(newSw) && oldPort.equals(newPort));
     }
 
-    protected boolean isInSameArchipelago(DatapathId s1, DatapathId s2) {
+    public boolean isInSameArchipelago(DatapathId s1, DatapathId s2) {
         for (Archipelago a : archipelagos) {
             if (a.getSwitches().contains(s1) && a.getSwitches().contains(s2)) {
                 return true;
@@ -1309,15 +1309,15 @@ public class TopologyInstance {
         return false;
     }
 
-    protected Set<DatapathId> getSwitches() {
+    public Set<DatapathId> getSwitches() {
         return switches;
     }
 
-    protected Set<OFPort> getPortsWithLinks(DatapathId sw) {
+    public Set<OFPort> getPortsWithLinks(DatapathId sw) {
         return portsWithLinks.get(sw);
     }
 
-    protected Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort) {
+    public Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort) {
         Set<OFPort> result = new HashSet<OFPort>();
         DatapathId clusterId = getClusterId(targetSw);
         for (NodePortTuple npt : clusterPorts.get(clusterId)) {
@@ -1328,15 +1328,15 @@ public class TopologyInstance {
         return result;
     }
 
-    protected Set<Link> getInternalInterClusterLinks() {
+    public Set<Link> getInternalInterClusterLinks() {
         return linksNonExternalInterCluster;
     }
 
-    protected Set<NodePortTuple> getAllBroadcastPorts() {
+    public Set<NodePortTuple> getAllBroadcastPorts() {
         return portsBroadcastAll;
     }
 
-    protected Set<DatapathId> getClusterIdsInArchipelago(DatapathId sw) {
+    public Set<DatapathId> getClusterIdsInArchipelago(DatapathId sw) {
         Archipelago a = getArchipelago(sw);
         if (a != null) {
             return a.getClusters().stream().map(c -> c.getId()).collect(Collectors.toSet());
@@ -1406,7 +1406,7 @@ public class TopologyInstance {
         }
     }
 
-    protected Set<NodePortTuple> getBroadcastPortsInArchipelago(DatapathId sw) {
+    public Set<NodePortTuple> getBroadcastPortsInArchipelago(DatapathId sw) {
         Archipelago a = getArchipelago(sw);
         if (a != null) {
             return portsBroadcastPerArchipelago.get(a.getId());
@@ -1414,7 +1414,7 @@ public class TopologyInstance {
         return ImmutableSet.of();
     }
     
-    protected Set<DatapathId> getArchipelagoIds() {
+    public Set<DatapathId> getArchipelagoIds() {
         return archipelagos.stream().map(a -> a.getId()).collect(Collectors.toSet());
     }
 } 
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index f5ad1592d488bb8c6ad85653db38c253c147c5f4..d5b1729c87838e12dfb79fcd8a99c6426fd0a2c3 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -34,7 +34,7 @@ import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.LLDP;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.routing.IRoutingService;
-import net.floodlightcontroller.routing.Route;
+import net.floodlightcontroller.routing.IRoutingService.PATH_METRIC;
 import net.floodlightcontroller.routing.web.RoutingWebRoutable;
 import net.floodlightcontroller.statistics.IStatisticsService;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
@@ -62,1115 +62,1079 @@ import java.util.concurrent.TimeUnit;
  * of the network graph, as well as implementing tools for finding routes
  * through the topology.
  */
-public class TopologyManager implements IFloodlightModule, ITopologyService, IRoutingService, ILinkDiscoveryListener, IOFMessageListener {
-	protected static Logger log = LoggerFactory.getLogger(TopologyManager.class);
-	public static final String MODULE_NAME = "topology";
-
-	protected static IStatisticsService statisticsService;
-
-	protected static volatile PATH_METRIC pathMetric = PATH_METRIC.HOPCOUNT_AVOID_TUNNELS; //default: compute paths on hop count
-	protected static boolean collectStatistics = false;
-
-	/**
-	 * Maximum number of route entries stored in memory.
-	 */
-	private static volatile int maxPathsToCompute = 3;
-
-	/**
-	 * Role of the controller.
-	 */
-	private HARole role;
-
-	/**
-	 * Set of ports for each switch
-	 */
-	protected Map<DatapathId, Set<OFPort>> switchPorts;
-
-	/**
-	 * Set of links organized by node port tuple
-	 */
-	protected Map<NodePortTuple, Set<Link>> switchPortLinks;
-
-	/**
-	 * Set of direct links
-	 */
-	protected Map<NodePortTuple, Set<Link>> directLinks;
-
-	/**
-	 * set of links that are broadcast domain links.
-	 */
-	protected Map<NodePortTuple, Set<Link>> interClusterLinks;
-
-	/**
-	 * set of tunnel links
-	 */
-	protected Set<NodePortTuple> tunnelPorts;
-
-	protected ILinkDiscoveryService linkDiscoveryService;
-	protected IThreadPoolService threadPoolService;
-	protected IFloodlightProviderService floodlightProviderService;
-	protected IOFSwitchService switchService;
-	protected IRestApiService restApiService;
-	protected IDebugCounterService debugCounterService;
-
-	// Modules that listen to our updates
-	protected ArrayList<ITopologyListener> topologyAware;
-
-	protected BlockingQueue<LDUpdate> ldUpdates;
-
-	// These must be accessed using getCurrentInstance(), not directly
-	protected TopologyInstance currentInstance;
-
-	protected SingletonTask newInstanceTask;
-	private Date lastUpdateTime;
-
-	/**
-	 * Flag that indicates if links (direct/tunnel/multihop links) were
-	 * updated as part of LDUpdate.
-	 */
-	protected boolean linksUpdated;
-	/**
-	 * Flag that indicates if direct or tunnel links were updated as
-	 * part of LDUpdate.
-	 */
-	protected boolean dtLinksUpdated;
-
-	/** Flag that indicates if tunnel ports were updated or not
-	 */
-	protected boolean tunnelPortsUpdated;
-
-	protected int TOPOLOGY_COMPUTE_INTERVAL_MS = 500;
-
-	private IHAListener haListener;
-
-	/**
-	 *  Debug Counters
-	 */
-	protected static final String PACKAGE = TopologyManager.class.getPackage().getName();
-	protected IDebugCounter ctrIncoming;
-
-	//  Getter/Setter methods
-	/**
-	 * Get the time interval for the period topology updates, if any.
-	 * The time returned is in milliseconds.
-	 * @return
-	 */
-	public int getTopologyComputeInterval() {
-		return TOPOLOGY_COMPUTE_INTERVAL_MS;
-	}
-
-	/**
-	 * Set the time interval for the period topology updates, if any.
-	 * The time is in milliseconds.
-	 * @return
-	 */
-	public void setTopologyComputeInterval(int time_ms) {
-		TOPOLOGY_COMPUTE_INTERVAL_MS = time_ms;
-	}
-
-	/**
-	 * Thread for recomputing topology.  The thread is always running,
-	 * however the function applyUpdates() has a blocking call.
-	 */
-	protected class UpdateTopologyWorker implements Runnable {
-		@Override
-		public void run() {
-			try {
-				if (ldUpdates.peek() != null) {
-					updateTopology();
-				}
-				handleMiscellaneousPeriodicEvents();
-			}
-			catch (Exception e) {
-				log.error("Error in topology instance task thread", e);
-			} finally {
-				if (floodlightProviderService.getRole() != HARole.STANDBY) {
-					newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS);
-				}
-			}
-		}
-	}
-
-	// To be used for adding any periodic events that's required by topology.
-	protected void handleMiscellaneousPeriodicEvents() {
-		return;
-	}
-
-	public boolean updateTopology() {
-		boolean newInstanceFlag;
-		linksUpdated = false;
-		dtLinksUpdated = false;
-		tunnelPortsUpdated = false;
-		List<LDUpdate> appliedUpdates = applyUpdates();
-		newInstanceFlag = createNewInstance("link-discovery-updates");
-		lastUpdateTime = new Date();
-		informListeners(appliedUpdates);
-		return newInstanceFlag;
-	}
-
-	// **********************
-	// ILinkDiscoveryListener
-	// **********************
-
-	@Override
-	public void linkDiscoveryUpdate(List<LDUpdate> updateList) {
-		if (log.isTraceEnabled()) {
-			log.trace("Queuing update: {}", updateList);
-		}
-		ldUpdates.addAll(updateList);
-	}
-
-	// ****************
-	// ITopologyService
-	// ****************
-
-	@Override
-	public Map<DatapathId, Set<Link>> getAllLinks() {
-
-		Map<DatapathId, Set<Link>> dpidLinks = new HashMap<DatapathId, Set<Link>>();
-		TopologyInstance ti = getCurrentInstance();
-		Set<DatapathId> switches = ti.getSwitches();
-
-		for(DatapathId s: switches) {
-			if (this.switchPorts.get(s) == null) continue;
-			for (OFPort p: switchPorts.get(s)) {
-				NodePortTuple np = new NodePortTuple(s, p);
-				if (this.switchPortLinks.get(np) == null) continue;
-				for(Link l: this.switchPortLinks.get(np)) {
-					if(dpidLinks.containsKey(s)) {
-						dpidLinks.get(s).add(l);
-					}
-					else {
-						dpidLinks.put(s,new HashSet<Link>(Arrays.asList(l)));
-					}
-
-				}
-			}
-		}
+public class TopologyManager implements IFloodlightModule, ITopologyService, 
+    ITopologyManagerBackend, ILinkDiscoveryListener, IOFMessageListener {
+
+    protected static Logger log = LoggerFactory.getLogger(TopologyManager.class);
+    public static final String MODULE_NAME = "topology";
+
+    protected static IStatisticsService statisticsService;
+
+    protected static volatile PATH_METRIC pathMetric = PATH_METRIC.HOPCOUNT_AVOID_TUNNELS; //default: compute paths on hop count
+    protected static boolean collectStatistics = false;
+
+    /**
+     * Maximum number of route entries stored in memory.
+     */
+    private static volatile int maxPathsToCompute = 3;
+
+    /**
+     * Role of the controller.
+     */
+    private HARole role;
+
+    /**
+     * Set of ports for each switch
+     */
+    protected Map<DatapathId, Set<OFPort>> switchPorts;
+
+    /**
+     * Set of links organized by node port tuple
+     */
+    protected Map<NodePortTuple, Set<Link>> switchPortLinks;
+
+    /**
+     * Set of direct links
+     */
+    protected Map<NodePortTuple, Set<Link>> directLinks;
+
+    /**
+     * set of links that are broadcast domain links.
+     */
+    protected Map<NodePortTuple, Set<Link>> interClusterLinks;
+
+    /**
+     * set of tunnel links
+     */
+    protected Set<NodePortTuple> tunnelPorts;
+
+    protected ILinkDiscoveryService linkDiscoveryService;
+    protected IThreadPoolService threadPoolService;
+    protected IFloodlightProviderService floodlightProviderService;
+    protected IOFSwitchService switchService;
+    protected IRestApiService restApiService;
+    protected IDebugCounterService debugCounterService;
+
+    // Modules that listen to our updates
+    protected ArrayList<ITopologyListener> topologyAware;
+
+    protected BlockingQueue<LDUpdate> ldUpdates;
+
+    // These must be accessed using getCurrentInstance(), not directly
+    protected TopologyInstance currentInstance;
+
+    protected SingletonTask newInstanceTask;
+    private Date lastUpdateTime;
+
+    /**
+     * Flag that indicates if links (direct/tunnel/multihop links) were
+     * updated as part of LDUpdate.
+     */
+    protected boolean linksUpdated;
+    /**
+     * Flag that indicates if direct or tunnel links were updated as
+     * part of LDUpdate.
+     */
+    protected boolean dtLinksUpdated;
+
+    /** Flag that indicates if tunnel ports were updated or not
+     */
+    protected boolean tunnelPortsUpdated;
+
+    protected int TOPOLOGY_COMPUTE_INTERVAL_MS = 500;
+
+    private IHAListener haListener;
+
+    /**
+     *  Debug Counters
+     */
+    protected static final String PACKAGE = TopologyManager.class.getPackage().getName();
+    protected IDebugCounter ctrIncoming;
+
+    //  Getter/Setter methods
+    /**
+     * Get the time interval for the period topology updates, if any.
+     * The time returned is in milliseconds.
+     * @return
+     */
+    public int getTopologyComputeInterval() {
+        return TOPOLOGY_COMPUTE_INTERVAL_MS;
+    }
+
+    /**
+     * Set the time interval for the period topology updates, if any.
+     * The time is in milliseconds.
+     * @return
+     */
+    public void setTopologyComputeInterval(int time_ms) {
+        TOPOLOGY_COMPUTE_INTERVAL_MS = time_ms;
+    }
+
+    /**
+     * Thread for recomputing topology.  The thread is always running,
+     * however the function applyUpdates() has a blocking call.
+     */
+    protected class UpdateTopologyWorker implements Runnable {
+        @Override
+        public void run() {
+            try {
+                if (ldUpdates.peek() != null) {
+                    updateTopology();
+                }
+                handleMiscellaneousPeriodicEvents();
+            }
+            catch (Exception e) {
+                log.error("Error in topology instance task thread", e);
+            } finally {
+                if (floodlightProviderService.getRole() != HARole.STANDBY) {
+                    newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS);
+                }
+            }
+        }
+    }
+
+    // To be used for adding any periodic events that's required by topology.
+    protected void handleMiscellaneousPeriodicEvents() {
+        return;
+    }
+
+    public boolean updateTopology() {
+        boolean newInstanceFlag;
+        linksUpdated = false;
+        dtLinksUpdated = false;
+        tunnelPortsUpdated = false;
+        List<LDUpdate> appliedUpdates = applyUpdates();
+        newInstanceFlag = createNewInstance("link-discovery-updates");
+        lastUpdateTime = new Date();
+        informListeners(appliedUpdates);
+        return newInstanceFlag;
+    }
+
+    // **********************
+    // ILinkDiscoveryListener
+    // **********************
+
+    @Override
+    public void linkDiscoveryUpdate(List<LDUpdate> updateList) {
+        if (log.isTraceEnabled()) {
+            log.trace("Queuing update: {}", updateList);
+        }
+        ldUpdates.addAll(updateList);
+    }
+
+    // ****************
+    // ITopologyService
+    // ****************
+
+    @Override
+    public Map<DatapathId, Set<Link>> getAllLinks() {
+
+        Map<DatapathId, Set<Link>> dpidLinks = new HashMap<DatapathId, Set<Link>>();
+        TopologyInstance ti = getCurrentInstance();
+        Set<DatapathId> switches = ti.getSwitches();
+
+        for(DatapathId s: switches) {
+            if (this.switchPorts.get(s) == null) continue;
+            for (OFPort p: switchPorts.get(s)) {
+                NodePortTuple np = new NodePortTuple(s, p);
+                if (this.switchPortLinks.get(np) == null) continue;
+                for(Link l: this.switchPortLinks.get(np)) {
+                    if(dpidLinks.containsKey(s)) {
+                        dpidLinks.get(s).add(l);
+                    }
+                    else {
+                        dpidLinks.put(s,new HashSet<Link>(Arrays.asList(l)));
+                    }
+
+                }
+            }
+        }
+
+        return dpidLinks;
+    }
+
+    @Override
+    public boolean isEdge(DatapathId sw, OFPort p){
+        TopologyInstance ti = getCurrentInstance();
+        return ti.isEdge(sw, p);
+    }
+
+    @Override
+    public Set<OFPort> getSwitchBroadcastPorts(DatapathId sw){
+        TopologyInstance ti = getCurrentInstance();
+        return ti.swBroadcastPorts(sw);
+    }
+
+    @Override
+    public Date getLastUpdateTime() {
+        return lastUpdateTime;
+    }
 
-		return dpidLinks;
-	}
-
-	@Override
-	public boolean isEdge(DatapathId sw, OFPort p){
-		TopologyInstance ti = getCurrentInstance();
-		return ti.isEdge(sw, p);
-	}
-
-	@Override
-	public Set<OFPort> getSwitchBroadcastPorts(DatapathId sw){
-		TopologyInstance ti = getCurrentInstance();
-		return ti.swBroadcastPorts(sw);
-	}
-
-	@Override
-	public Date getLastUpdateTime() {
-		return lastUpdateTime;
-	}
-
-	@Override
-	public void addListener(ITopologyListener listener) {
-		topologyAware.add(listener);
-	}
-	
-	@Override
+    @Override
+    public void addListener(ITopologyListener listener) {
+        topologyAware.add(listener);
+    }
+
+    @Override
     public void removeListener(ITopologyListener listener) {
         topologyAware.remove(listener);
     }
 
-	@Override
-	public boolean isAttachmentPointPort(DatapathId switchid, OFPort port) {
-
-		// If the switch port is 'tun-bsn' port, it is not
-		// an attachment point port, irrespective of whether
-		// a link is found through it or not.
-		if (linkDiscoveryService.isTunnelPort(switchid, port))
-			return false;
-
-		TopologyInstance ti = getCurrentInstance();
-
-		// if the port is not attachment point port according to
-		// topology instance, then return false
-		if (ti.isAttachmentPointPort(switchid, port) == false)
-			return false;
-
-		// Check whether the port is a physical port. We should not learn
-		// attachment points on "special" ports.
-		if ((port.getShortPortNumber() & 0xff00) == 0xff00 && port.getShortPortNumber() != (short)0xfffe) return false;
-
-		// Make sure that the port is enabled.
-		IOFSwitch sw = switchService.getActiveSwitch(switchid);
-		if (sw == null) return false;
-		return (sw.portEnabled(port));
-	}
-
-	@Override
-	public DatapathId getClusterId(DatapathId switchId) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.getClusterId(switchId);
-	}
-
-	@Override
-	public boolean isInSameCluster(DatapathId switch1, DatapathId switch2) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.isInSameCluster(switch1, switch2);
-	}
-
-	@Override
-	public boolean isNotBlocked(DatapathId sw, OFPort port) {
-	    TopologyInstance ti = getCurrentInstance();
-	    return !ti.isBlockedPort(new NodePortTuple(sw, port));
-	}
-
-	@Override
-	public PATH_METRIC setPathMetric(PATH_METRIC metric) {
-		pathMetric = metric;
-		return pathMetric;
-	}
-
-	@Override
-	public PATH_METRIC getPathMetric() {
-		return pathMetric;
-	}
-
-	protected static PATH_METRIC getPathMetricInternal() {
-		return pathMetric;
-	}
-	
-	protected static int getMaxPathsToComputeInternal() {
-	    return maxPathsToCompute;
-	}
-	
-	@Override
-	public int getMaxPathsToCompute() {
-	    return maxPathsToCompute;
-	}
-	
-	@Override
-	public void setMaxPathsToCompute(int max) {
-	    maxPathsToCompute = max;
-	}
-
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	@Override
-	public boolean isBroadcastAllowed(DatapathId sw, OFPort portId) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.isBroadcastAllowedOnSwitchPort(sw, portId);
-	}
-
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	@Override
-	public Set<OFPort> getPortsWithLinks(DatapathId sw) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.getPortsWithLinks(sw);
-	}
-
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-	
-	/** 
-	 * Get all the ports on the target switch (targetSw) on which a
-	 * broadcast packet must be sent from a host whose attachment point
-	 * is on switch port (src, srcPort).
-	 */
-	@Override
-	public Set<OFPort> getBroadcastPorts(DatapathId targetSw,
-			DatapathId src, OFPort srcPort) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.getBroadcastPorts(targetSw, src, srcPort);
-	}
-
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	@Override
-	public boolean isInSameArchipelago(DatapathId s1, DatapathId s2) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.isInSameArchipelago(s1, s2);
-
-	}
-
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	@Override
-	public boolean isBroadcastPort(DatapathId sw, OFPort port) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.isBroadcastPort(new NodePortTuple(sw, port));
-	}
-
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	@Override
-	public boolean isConsistent(DatapathId oldSw, OFPort oldPort,
-			DatapathId newSw, OFPort newPort) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.isConsistent(oldSw, oldPort, newSw, newPort);
-	}
-
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	@Override
-	public Set<DatapathId> getSwitchesInCluster(DatapathId switchDPID) {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.getSwitchesInCluster(switchDPID);
-	}
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	@Override
-	public Set<Link> getExternalInterClusterLinks() {
-	    ImmutableSet.Builder<Link> b = ImmutableSet.builder();
+    @Override
+    public boolean isAttachmentPointPort(DatapathId switchid, OFPort port) {
+
+        // If the switch port is 'tun-bsn' port, it is not
+        // an attachment point port, irrespective of whether
+        // a link is found through it or not.
+        if (linkDiscoveryService.isTunnelPort(switchid, port))
+            return false;
+
+        TopologyInstance ti = getCurrentInstance();
+
+        // if the port is not attachment point port according to
+        // topology instance, then return false
+        if (ti.isAttachmentPointPort(switchid, port) == false)
+            return false;
+
+        // Check whether the port is a physical port. We should not learn
+        // attachment points on "special" ports.
+        if ((port.getShortPortNumber() & 0xff00) == 0xff00 && port.getShortPortNumber() != (short)0xfffe) return false;
+
+        // Make sure that the port is enabled.
+        IOFSwitch sw = switchService.getActiveSwitch(switchid);
+        if (sw == null) return false;
+        return (sw.portEnabled(port));
+    }
+
+    @Override
+    public DatapathId getClusterId(DatapathId switchId) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.getClusterId(switchId);
+    }
+
+    @Override
+    public boolean isInSameCluster(DatapathId switch1, DatapathId switch2) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.isInSameCluster(switch1, switch2);
+    }
+
+    @Override
+    public boolean isNotBlocked(DatapathId sw, OFPort port) {
+        TopologyInstance ti = getCurrentInstance();
+        return !ti.isBlockedPort(new NodePortTuple(sw, port));
+    }
+
+    @Override
+    public void setPathMetric(PATH_METRIC metric) {
+        pathMetric = metric;
+    }
+
+    @Override
+    public PATH_METRIC getPathMetric() {
+        return pathMetric;
+    }
+
+    protected static PATH_METRIC getPathMetricInternal() {
+        return pathMetric;
+    }
+
+    protected static int getMaxPathsToComputeInternal() {
+        return maxPathsToCompute;
+    }
+
+    @Override
+    public int getMaxPathsToCompute() {
+        return maxPathsToCompute;
+    }
+
+    @Override
+    public void setMaxPathsToCompute(int max) {
+        maxPathsToCompute = max;
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public boolean isBroadcastAllowed(DatapathId sw, OFPort portId) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.isBroadcastAllowedOnSwitchPort(sw, portId);
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public Set<OFPort> getPortsWithLinks(DatapathId sw) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.getPortsWithLinks(sw);
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    /** 
+     * Get all the ports on the target switch (targetSw) on which a
+     * broadcast packet must be sent from a host whose attachment point
+     * is on switch port (src, srcPort).
+     */
+    @Override
+    public Set<OFPort> getBroadcastPorts(DatapathId targetSw,
+            DatapathId src, OFPort srcPort) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.getBroadcastPorts(targetSw, src, srcPort);
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public boolean isInSameArchipelago(DatapathId s1, DatapathId s2) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.isInSameArchipelago(s1, s2);
+
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public boolean isBroadcastPort(DatapathId sw, OFPort port) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.isBroadcastPort(new NodePortTuple(sw, port));
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public boolean isConsistent(DatapathId oldSw, OFPort oldPort,
+            DatapathId newSw, OFPort newPort) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.isConsistent(oldSw, oldPort, newSw, newPort);
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public Set<DatapathId> getSwitchesInCluster(DatapathId switchDPID) {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.getSwitchesInCluster(switchDPID);
+    }
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public Set<Link> getExternalInterClusterLinks() {
+        ImmutableSet.Builder<Link> b = ImmutableSet.builder();
         for (Collection<Link> c : interClusterLinks.values()) {
             for (Link l : c) {
                 b.add(l);
             }
         }
         return b.build();
-	}
-	
-	@Override
+    }
+
+    @Override
     public Set<Link> getInternalInterClusterLinks() {
         TopologyInstance ti = getCurrentInstance();
         return ti.getInternalInterClusterLinks();
     }
 
-	@Override
-	public Set<NodePortTuple> getTunnelPorts() {
-		return tunnelPorts;
-	}
-
-	@Override
-	public Set<NodePortTuple> getBlockedPorts() {
-		Set<NodePortTuple> bp;
-		Set<NodePortTuple> blockedPorts =
-				new HashSet<NodePortTuple>();
-
-		bp = getCurrentInstance().getBlockedPorts();
-		if (bp != null)
-			blockedPorts.addAll(bp);
-
-		return blockedPorts;
-	}
-	////////////////////////////////////////////////////////////////////////
-	////////////////////////////////////////////////////////////////////////
-
-	// ***************
-	// IRoutingService
-	// ***************
-
-	@Override
-	public Route getPath(DatapathId src, DatapathId dst) {
-	    TopologyInstance ti = getCurrentInstance();
-        return ti.getPath(src, dst);
-	}
-	
-	@Override
-	public Route getPath(DatapathId src, OFPort srcPort, DatapathId dst, OFPort dstPort) {
-	    TopologyInstance ti = getCurrentInstance();
-        return ti.getPath(src, srcPort, dst, dstPort);
-    }
-
-	@Override
-	public boolean pathExists(DatapathId src, DatapathId dst) {
-	    TopologyInstance ti = getCurrentInstance();
-        return ti.pathExists(src, dst);
-	}
-
-	@Override
-	public List<Route> getPathsFast(DatapathId srcDpid, DatapathId dstDpid) {
-        return getCurrentInstance().getPathsFast(srcDpid, dstDpid, maxPathsToCompute);
-	}
-
-	@Override
-	public List<Route> getPathsFast(DatapathId srcDpid, DatapathId dstDpid, int k) {
-		return getCurrentInstance().getPathsFast(srcDpid, dstDpid, k);
-	}
-
-	@Override
-	public List<Route> getPathsSlow(DatapathId srcDpid, DatapathId dstDpid, int k) {
-		return getCurrentInstance().getPathsSlow(srcDpid, dstDpid, k);
-	}
-
-	public Map<Link, Integer> getLinkCostMap() {
-		TopologyInstance ti = getCurrentInstance();
-		return ti.initLinkCostMap();
-	}
-
-	// ******************
-	// IOFMessageListener
-	// ******************
-
-	@Override
-	public String getName() {
-		return MODULE_NAME;
-	}
-
-	@Override
-	public boolean isCallbackOrderingPrereq(OFType type, String name) {
-		return "linkdiscovery".equals(name);
-	}
-
-	@Override
-	public boolean isCallbackOrderingPostreq(OFType type, String name) {
-		return false;
-	}
-
-	@Override
-	public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-		switch (msg.getType()) {
-		case PACKET_IN:
-			ctrIncoming.increment();
-			return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
-		default:
-			break;
-		}
+    @Override
+    public Set<NodePortTuple> getTunnelPorts() {
+        return tunnelPorts;
+    }
 
-		return Command.CONTINUE;
-	}
-
-	// ***************
-	// IHAListener
-	// ***************
-
-	private class HAListenerDelegate implements IHAListener {
-		@Override
-		public void transitionToActive() {
-			role = HARole.ACTIVE;
-			log.debug("Re-computing topology due " +
-					"to HA change from STANDBY->ACTIVE");
-			newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS,
-					TimeUnit.MILLISECONDS);
-		}
+    @Override
+    public Set<NodePortTuple> getBlockedPorts() {
+        Set<NodePortTuple> bp;
+        Set<NodePortTuple> blockedPorts =
+                new HashSet<NodePortTuple>();
 
-		@Override
-		public void controllerNodeIPsChanged(
-				Map<String, String> curControllerNodeIPs,
-				Map<String, String> addedControllerNodeIPs,
-				Map<String, String> removedControllerNodeIPs) {
-		}
+        bp = getCurrentInstance().getBlockedPorts();
+        if (bp != null)
+            blockedPorts.addAll(bp);
 
-		@Override
-		public String getName() {
-			return TopologyManager.this.getName();
-		}
+        return blockedPorts;
+    }
+    ////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////
 
-		@Override
-		public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type,
-				String name) {
-			return "linkdiscovery".equals(name);
-		}
+    public Map<Link, Integer> getLinkCostMap() {
+        TopologyInstance ti = getCurrentInstance();
+        return ti.initLinkCostMap();
+    }
 
-		@Override
-		public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type,
-				String name) {
-			return false;
-		}
+    // ******************
+    // IOFMessageListener
+    // ******************
 
-		@Override
-		public void transitionToStandby() { }
-	}
-
-	// *****************
-	// IFloodlightModule
-	// *****************
-
-	@Override
-	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-		Collection<Class<? extends IFloodlightService>> l =
-				new ArrayList<Class<? extends IFloodlightService>>();
-		l.add(ITopologyService.class);
-		l.add(IRoutingService.class);
-		return l;
-	}
-
-	@Override
-	public Map<Class<? extends IFloodlightService>, IFloodlightService>
-	getServiceImpls() {
-		Map<Class<? extends IFloodlightService>,
-		IFloodlightService> m =
-		new HashMap<Class<? extends IFloodlightService>,
-		IFloodlightService>();
-		// We are the class that implements the service
-		m.put(ITopologyService.class, this);
-		m.put(IRoutingService.class, this);
-		return m;
-	}
-
-	@Override
-	public Collection<Class<? extends IFloodlightService>>
-	getModuleDependencies() {
-		Collection<Class<? extends IFloodlightService>> l =
-				new ArrayList<Class<? extends IFloodlightService>>();
-		l.add(ILinkDiscoveryService.class);
-		l.add(IThreadPoolService.class);
-		l.add(IFloodlightProviderService.class);
-		l.add(IOFSwitchService.class);
-		l.add(IDebugCounterService.class);
-		l.add(IRestApiService.class);
-		return l;
-	}
-
-	@Override
-	public void init(FloodlightModuleContext context)
-			throws FloodlightModuleException {
-		linkDiscoveryService = context.getServiceImpl(ILinkDiscoveryService.class);
-		threadPoolService = context.getServiceImpl(IThreadPoolService.class);
-		floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
-		switchService = context.getServiceImpl(IOFSwitchService.class);
-		restApiService = context.getServiceImpl(IRestApiService.class);
-		debugCounterService = context.getServiceImpl(IDebugCounterService.class);
-		statisticsService = context.getServiceImpl(IStatisticsService.class);
-
-		switchPorts = new HashMap<DatapathId, Set<OFPort>>();
-		switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
-		directLinks = new HashMap<NodePortTuple, Set<Link>>();
-		interClusterLinks = new HashMap<NodePortTuple, Set<Link>>();
-		tunnelPorts = new HashSet<NodePortTuple>();
-		topologyAware = new ArrayList<ITopologyListener>();
-		ldUpdates = new LinkedBlockingQueue<LDUpdate>();
-		haListener = new HAListenerDelegate();
-		registerTopologyDebugCounters();
-
-		Map<String, String> configOptions = context.getConfigParams(this);
-		String metric = configOptions.get("pathMetric") != null
-				? configOptions.get("pathMetric").trim().toLowerCase() : null;
-		if (metric != null) {
-		    metric = metric.toLowerCase().trim();
-			switch (metric) {
-				case "latency":
-				    pathMetric = PATH_METRIC.LATENCY;
-					break;
-				case "utilization":
-				    pathMetric = PATH_METRIC.UTILIZATION;
-					break;
-				case "hopcount":
-				    pathMetric = PATH_METRIC.HOPCOUNT;
-					break;
-				case "hopcount_avoid_tunnels":
-				    pathMetric = PATH_METRIC.HOPCOUNT_AVOID_TUNNELS;
-					break;
-				case "link_speed":
-				    pathMetric = PATH_METRIC.LINK_SPEED;
-					break;
-				default:
-					log.error("Invalid routing metric {}. Using default {}", metric, pathMetric.getMetricName());
-					break;
-			}
-		}
-		log.info("Path metrics set to {}", pathMetric);
-
-		String maxroutes = configOptions.get("maxPathsToCompute") != null
-				? configOptions.get("maxPathsToCompute").trim() : null;
-		if (maxroutes != null) {
-		    try {
-		        maxPathsToCompute = Integer.parseInt(maxroutes);
-		    } catch (NumberFormatException e) {
-		        log.error("Invalid 'maxPathsToCompute'. Using default {}", maxPathsToCompute);
-		    }
-		}
-		log.info("Will compute a max of {} paths upon topology updates", maxPathsToCompute);
-	}
+    @Override
+    public String getName() {
+        return MODULE_NAME;
+    }
 
-	@Override
-	public void startUp(FloodlightModuleContext context) {
-		clearCurrentTopology();
-		// Initialize role to floodlight provider role.
-		this.role = floodlightProviderService.getRole();
+    @Override
+    public boolean isCallbackOrderingPrereq(OFType type, String name) {
+        return "linkdiscovery".equals(name);
+    }
 
-		ScheduledExecutorService ses = threadPoolService.getScheduledExecutor();
-		newInstanceTask = new SingletonTask(ses, new UpdateTopologyWorker());
+    @Override
+    public boolean isCallbackOrderingPostreq(OFType type, String name) {
+        return false;
+    }
 
-		if (role != HARole.STANDBY) {
-			newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS);
-		}
+    @Override
+    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+        switch (msg.getType()) {
+        case PACKET_IN:
+            ctrIncoming.increment();
+            return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
+        default:
+            break;
+        }
 
-		linkDiscoveryService.addListener(this);
-		floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);
-		floodlightProviderService.addHAListener(this.haListener);
-		addRestletRoutable();
-	}
+        return Command.CONTINUE;
+    }
 
-	private void registerTopologyDebugCounters() throws FloodlightModuleException {
-		if (debugCounterService == null) {
-			log.error("debugCounterService should not be null. Has IDebugEventService been loaded previously?");
-		}
-		debugCounterService.registerModule(PACKAGE);
-		ctrIncoming = debugCounterService.registerCounter(
-				PACKAGE, "incoming",
-				"All incoming packets seen by this module");
-	}
-
-	protected void addRestletRoutable() {
-		restApiService.addRestletRoutable(new TopologyWebRoutable());
-		restApiService.addRestletRoutable(new RoutingWebRoutable());
-	}
-
-	// ****************
-	// Internal methods
-	// ****************
-	/**
-	 * If the packet-in switch port is disabled for all data traffic, then
-	 * the packet will be dropped.  Otherwise, the packet will follow the
-	 * normal processing chain.
-	 * @param sw
-	 * @param pi
-	 * @param cntx
-	 * @return
-	 */
-	protected Command dropFilter(DatapathId sw, OFPacketIn pi,
-			FloodlightContext cntx) {
-		Command result = Command.CONTINUE;
-		OFPort inPort = (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT));
-
-		// If the input port is not allowed for data traffic, drop everything.
-		// BDDP packets will not reach this stage.
-		if (isNotBlocked(sw, inPort) == false) {
-			if (log.isTraceEnabled()) {
-				log.trace("Ignoring packet because of topology " +
-						"restriction on switch={}, port={}", sw.getLong(), inPort.getPortNumber());
-				result = Command.STOP;
-			}
-		}
-		return result;
-	}
-
-	/**
-	 * Send a packet-out to multiple ports
-	 * @param packetData
-	 * @param sw
-	 * @param ports
-	 * @param cntx
-	 */
-	public void doMultiActionPacketOut(byte[] packetData, IOFSwitch sw,
-			Set<OFPort> ports,
-			FloodlightContext cntx) {
-
-		if (ports == null) return;
-		if (packetData == null || packetData.length <= 0) return;
-
-		//OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT);
-		OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
-		List<OFAction> actions = new ArrayList<OFAction>();
-		for(OFPort p: ports) {
-			//actions.add(new OFActionOutput(p, (short) 0));
-			actions.add(sw.getOFFactory().actions().output(p, 0));
-		}
+    // ***************
+    // IHAListener
+    // ***************
+
+    private class HAListenerDelegate implements IHAListener {
+        @Override
+        public void transitionToActive() {
+            role = HARole.ACTIVE;
+            log.debug("Re-computing topology due " +
+                    "to HA change from STANDBY->ACTIVE");
+            newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS,
+                    TimeUnit.MILLISECONDS);
+        }
+
+        @Override
+        public void controllerNodeIPsChanged(
+                Map<String, String> curControllerNodeIPs,
+                Map<String, String> addedControllerNodeIPs,
+                Map<String, String> removedControllerNodeIPs) {
+        }
+
+        @Override
+        public String getName() {
+            return TopologyManager.this.getName();
+        }
 
-		// set actions
-		pob.setActions(actions);
-		// set action length
-		//po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * ports.size()));
-		// set buffer-id to BUFFER_ID_NONE
-		pob.setBufferId(OFBufferId.NO_BUFFER);
-		// set in-port to OFPP_NONE
-		pob.setInPort(OFPort.ZERO);
+        @Override
+        public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type,
+                String name) {
+            return "linkdiscovery".equals(name);
+        }
 
-		// set packet data
-		pob.setData(packetData);
+        @Override
+        public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type,
+                String name) {
+            return false;
+        }
 
-		// compute and set packet length.
-		//short poLength = (short)(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength() + packetData.length);
+        @Override
+        public void transitionToStandby() { }
+    }
 
-		//po.setLength(poLength);
+    // *****************
+    // IFloodlightModule
+    // *****************
 
-		//ctrIncoming.updatePktOutFMCounterStore(sw, po);
-		if (log.isTraceEnabled()) {
-			log.trace("write broadcast packet on switch-id={} " +
-					"interaces={} packet-data={} packet-out={}",
-					new Object[] {sw.getId(), ports, packetData, pob.build()});
-		}
-		sw.write(pob.build(), LogicalOFMessageCategory.MAIN);
-	}
-
-	/**
-	 * Get the set of ports to eliminate for sending out BDDP.  The method
-	 * returns all the ports that are suppressed for link discovery on the
-	 * switch.
-	 * packets.
-	 * @param sid
-	 * @return
-	 */
-	protected Set<OFPort> getPortsToEliminateForBDDP(DatapathId sid) {
-		Set<NodePortTuple> suppressedNptList = linkDiscoveryService.getSuppressLLDPsInfo();
-		if (suppressedNptList == null) return null;
-
-		Set<OFPort> resultPorts = new HashSet<OFPort>();
-		for(NodePortTuple npt: suppressedNptList) {
-			if (npt.getNodeId() == sid) {
-				resultPorts.add(npt.getPortId());
-			}
-		}
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+        Collection<Class<? extends IFloodlightService>> l =
+                new ArrayList<Class<? extends IFloodlightService>>();
+        l.add(ITopologyService.class);
+        l.add(IRoutingService.class);
+        return l;
+    }
 
-		return resultPorts;
-	}
-
-	/**
-	 * The BDDP packets are forwarded out of all the ports out of an
-	 * openflowdomain.  Get all the switches in the same openflow
-	 * domain as the sw (disabling tunnels).  Then get all the
-	 * external switch ports and send these packets out.
-	 * @param sw
-	 * @param pi
-	 * @param cntx
-	 */
-	protected void doFloodBDDP(DatapathId pinSwitch, OFPacketIn pi,
-			FloodlightContext cntx) {
-
-		TopologyInstance ti = getCurrentInstance();
-
-		Set<DatapathId> switches = ti.getSwitchesInCluster(pinSwitch);
-
-		if (switches == null)
-		{
-			// indicates no links are connected to the switches
-			switches = new HashSet<DatapathId>();
-			switches.add(pinSwitch);
-		}
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService>
+    getServiceImpls() {
+        Map<Class<? extends IFloodlightService>,
+        IFloodlightService> m =
+        new HashMap<Class<? extends IFloodlightService>,
+        IFloodlightService>();
+        // We are the class that implements the service
+        m.put(ITopologyService.class, this);
+        m.put(IRoutingService.class, this);
+        return m;
+    }
 
-		for (DatapathId sid : switches) {
-			IOFSwitch sw = switchService.getSwitch(sid);
-			if (sw == null) continue;
-			Collection<OFPort> enabledPorts = sw.getEnabledPortNumbers();
-			if (enabledPorts == null)
-				continue;
-			Set<OFPort> ports = new HashSet<OFPort>();
-			ports.addAll(enabledPorts);
-
-			// all the ports known to topology // without tunnels.
-			// out of these, we need to choose only those that are
-			// broadcast port, otherwise, we should eliminate.
-			Set<OFPort> portsKnownToTopo = ti.getPortsWithLinks(sid);
-
-			if (portsKnownToTopo != null) {
-				for (OFPort p : portsKnownToTopo) {
-					NodePortTuple npt =
-							new NodePortTuple(sid, p);
-					if (ti.isBroadcastPort(npt) == false) {
-						ports.remove(p);
-					}
-				}
-			}
-
-			Set<OFPort> portsToEliminate = getPortsToEliminateForBDDP(sid);
-			if (portsToEliminate != null) {
-				ports.removeAll(portsToEliminate);
-			}
-
-			// remove the incoming switch port
-			if (pinSwitch == sid) {
-				ports.remove((pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT)));
-			}
-
-			// we have all the switch ports to which we need to broadcast.
-			doMultiActionPacketOut(pi.getData(), sw, ports, cntx);
-		}
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+    getModuleDependencies() {
+        Collection<Class<? extends IFloodlightService>> l =
+                new ArrayList<Class<? extends IFloodlightService>>();
+        l.add(ILinkDiscoveryService.class);
+        l.add(IThreadPoolService.class);
+        l.add(IFloodlightProviderService.class);
+        l.add(IOFSwitchService.class);
+        l.add(IDebugCounterService.class);
+        l.add(IRestApiService.class);
+        return l;
+    }
 
-	}
+    @Override
+    public void init(FloodlightModuleContext context)
+            throws FloodlightModuleException {
+        linkDiscoveryService = context.getServiceImpl(ILinkDiscoveryService.class);
+        threadPoolService = context.getServiceImpl(IThreadPoolService.class);
+        floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
+        switchService = context.getServiceImpl(IOFSwitchService.class);
+        restApiService = context.getServiceImpl(IRestApiService.class);
+        debugCounterService = context.getServiceImpl(IDebugCounterService.class);
+        statisticsService = context.getServiceImpl(IStatisticsService.class);
+
+        switchPorts = new HashMap<DatapathId, Set<OFPort>>();
+        switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
+        directLinks = new HashMap<NodePortTuple, Set<Link>>();
+        interClusterLinks = new HashMap<NodePortTuple, Set<Link>>();
+        tunnelPorts = new HashSet<NodePortTuple>();
+        topologyAware = new ArrayList<ITopologyListener>();
+        ldUpdates = new LinkedBlockingQueue<LDUpdate>();
+        haListener = new HAListenerDelegate();
+        registerTopologyDebugCounters();
+
+        Map<String, String> configOptions = context.getConfigParams(this);
+        String metric = configOptions.get("pathMetric") != null
+                ? configOptions.get("pathMetric").trim().toLowerCase() : null;
+                if (metric != null) {
+                    metric = metric.toLowerCase().trim();
+                    switch (metric) {
+                    case "latency":
+                        pathMetric = PATH_METRIC.LATENCY;
+                        break;
+                    case "utilization":
+                        pathMetric = PATH_METRIC.UTILIZATION;
+                        break;
+                    case "hopcount":
+                        pathMetric = PATH_METRIC.HOPCOUNT;
+                        break;
+                    case "hopcount_avoid_tunnels":
+                        pathMetric = PATH_METRIC.HOPCOUNT_AVOID_TUNNELS;
+                        break;
+                    case "link_speed":
+                        pathMetric = PATH_METRIC.LINK_SPEED;
+                        break;
+                    default:
+                        log.error("Invalid routing metric {}. Using default {}", metric, pathMetric.getMetricName());
+                        break;
+                    }
+                }
+                log.info("Path metrics set to {}", pathMetric);
+
+                String maxroutes = configOptions.get("maxPathsToCompute") != null
+                        ? configOptions.get("maxPathsToCompute").trim() : null;
+                        if (maxroutes != null) {
+                            try {
+                                maxPathsToCompute = Integer.parseInt(maxroutes);
+                            } catch (NumberFormatException e) {
+                                log.error("Invalid 'maxPathsToCompute'. Using default {}", maxPathsToCompute);
+                            }
+                        }
+                        log.info("Will compute a max of {} paths upon topology updates", maxPathsToCompute);
+    }
 
-	protected Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
-		// get the packet-in switch.
-		Ethernet eth =
-				IFloodlightProviderService.bcStore.
-				get(cntx,IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+        clearCurrentTopology();
+        // Initialize role to floodlight provider role.
+        this.role = floodlightProviderService.getRole();
 
-		if (eth.getPayload() instanceof BSN) {
-			BSN bsn = (BSN) eth.getPayload();
-			if (bsn == null) return Command.STOP;
-			if (bsn.getPayload() == null) return Command.STOP;
+        ScheduledExecutorService ses = threadPoolService.getScheduledExecutor();
+        newInstanceTask = new SingletonTask(ses, new UpdateTopologyWorker());
 
-			// It could be a packet other than BSN LLDP, therefore
-			// continue with the regular processing.
-			if (bsn.getPayload() instanceof LLDP == false)
-				return Command.CONTINUE;
+        if (role != HARole.STANDBY) {
+            newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS);
+        }
 
-			doFloodBDDP(sw.getId(), pi, cntx);
-			return Command.STOP;
-		} else {
-			return dropFilter(sw.getId(), pi, cntx);
-		}
-	}
-
-	/**
-	 * Updates concerning switch disconnect and port down are not processed.
-	 * LinkDiscoveryManager is expected to process those messages and send
-	 * multiple link removed messages.  However, all the updates from
-	 * LinkDiscoveryManager would be propagated to the listeners of topology.
-	 */
-	public List<LDUpdate> applyUpdates() {
-		List<LDUpdate> appliedUpdates = new ArrayList<LDUpdate>();
-		LDUpdate update = null;
-		while (ldUpdates.peek() != null) {
-			try {
-				update = ldUpdates.take();
-			} catch (Exception e) {
-				log.error("Error reading link discovery update.", e);
-			}
-			if (log.isDebugEnabled()) {
-				log.debug("Applying update: {}", update);
-			}
-
-			switch (update.getOperation()) {
-			case LINK_UPDATED:
-				addOrUpdateLink(update.getSrc(), update.getSrcPort(),
-						update.getDst(), update.getDstPort(),
-						update.getLatency(), update.getType());
-				break;
-			case LINK_REMOVED:
-				removeLink(update.getSrc(), update.getSrcPort(),
-						update.getDst(), update.getDstPort());
-				break;
-			case SWITCH_UPDATED:
-				addOrUpdateSwitch(update.getSrc());
-				break;
-			case SWITCH_REMOVED:
-				removeSwitch(update.getSrc());
-				break;
-			case TUNNEL_PORT_ADDED:
-				addTunnelPort(update.getSrc(), update.getSrcPort());
-				break;
-			case TUNNEL_PORT_REMOVED:
-				removeTunnelPort(update.getSrc(), update.getSrcPort());
-				break;
-			case PORT_UP: case PORT_DOWN:
-				break;
-			}
-			// Add to the list of applied updates.
-			appliedUpdates.add(update);
-		}
-		return (Collections.unmodifiableList(appliedUpdates));
-	}
+        linkDiscoveryService.addListener(this);
+        floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);
+        floodlightProviderService.addHAListener(this.haListener);
+        addRestletRoutable();
+    }
+
+    private void registerTopologyDebugCounters() throws FloodlightModuleException {
+        if (debugCounterService == null) {
+            log.error("debugCounterService should not be null. Has IDebugEventService been loaded previously?");
+        }
+        debugCounterService.registerModule(PACKAGE);
+        ctrIncoming = debugCounterService.registerCounter(
+                PACKAGE, "incoming",
+                "All incoming packets seen by this module");
+    }
 
-	protected void addOrUpdateSwitch(DatapathId sw) {
-		/*TODO react appropriately
+    protected void addRestletRoutable() {
+        restApiService.addRestletRoutable(new TopologyWebRoutable());
+        restApiService.addRestletRoutable(new RoutingWebRoutable());
+    }
+
+    // ****************
+    // Internal methods
+    // ****************
+    /**
+     * If the packet-in switch port is disabled for all data traffic, then
+     * the packet will be dropped.  Otherwise, the packet will follow the
+     * normal processing chain.
+     * @param sw
+     * @param pi
+     * @param cntx
+     * @return
+     */
+    protected Command dropFilter(DatapathId sw, OFPacketIn pi,
+            FloodlightContext cntx) {
+        Command result = Command.CONTINUE;
+        OFPort inPort = (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT));
+
+        // If the input port is not allowed for data traffic, drop everything.
+        // BDDP packets will not reach this stage.
+        if (isNotBlocked(sw, inPort) == false) {
+            if (log.isTraceEnabled()) {
+                log.trace("Ignoring packet because of topology " +
+                        "restriction on switch={}, port={}", sw.getLong(), inPort.getPortNumber());
+                result = Command.STOP;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Send a packet-out to multiple ports
+     * @param packetData
+     * @param sw
+     * @param ports
+     * @param cntx
+     */
+    public void doMultiActionPacketOut(byte[] packetData, IOFSwitch sw,
+            Set<OFPort> ports,
+            FloodlightContext cntx) {
+
+        if (ports == null) return;
+        if (packetData == null || packetData.length <= 0) return;
+
+        //OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT);
+        OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
+        List<OFAction> actions = new ArrayList<OFAction>();
+        for(OFPort p: ports) {
+            //actions.add(new OFActionOutput(p, (short) 0));
+            actions.add(sw.getOFFactory().actions().output(p, 0));
+        }
+
+        // set actions
+        pob.setActions(actions);
+        // set action length
+        //po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * ports.size()));
+        // set buffer-id to BUFFER_ID_NONE
+        pob.setBufferId(OFBufferId.NO_BUFFER);
+        // set in-port to OFPP_NONE
+        pob.setInPort(OFPort.ZERO);
+
+        // set packet data
+        pob.setData(packetData);
+
+        // compute and set packet length.
+        //short poLength = (short)(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength() + packetData.length);
+
+        //po.setLength(poLength);
+
+        //ctrIncoming.updatePktOutFMCounterStore(sw, po);
+        if (log.isTraceEnabled()) {
+            log.trace("write broadcast packet on switch-id={} " +
+                    "interaces={} packet-data={} packet-out={}",
+                    new Object[] {sw.getId(), ports, packetData, pob.build()});
+        }
+        sw.write(pob.build(), LogicalOFMessageCategory.MAIN);
+    }
+
+    /**
+     * Get the set of ports to eliminate for sending out BDDP.  The method
+     * returns all the ports that are suppressed for link discovery on the
+     * switch.
+     * packets.
+     * @param sid
+     * @return
+     */
+    protected Set<OFPort> getPortsToEliminateForBDDP(DatapathId sid) {
+        Set<NodePortTuple> suppressedNptList = linkDiscoveryService.getSuppressLLDPsInfo();
+        if (suppressedNptList == null) return null;
+
+        Set<OFPort> resultPorts = new HashSet<OFPort>();
+        for(NodePortTuple npt: suppressedNptList) {
+            if (npt.getNodeId() == sid) {
+                resultPorts.add(npt.getPortId());
+            }
+        }
+
+        return resultPorts;
+    }
+
+    /**
+     * The BDDP packets are forwarded out of all the ports out of an
+     * openflowdomain.  Get all the switches in the same openflow
+     * domain as the sw (disabling tunnels).  Then get all the
+     * external switch ports and send these packets out.
+     * @param sw
+     * @param pi
+     * @param cntx
+     */
+    protected void doFloodBDDP(DatapathId pinSwitch, OFPacketIn pi,
+            FloodlightContext cntx) {
+
+        TopologyInstance ti = getCurrentInstance();
+
+        Set<DatapathId> switches = ti.getSwitchesInCluster(pinSwitch);
+
+        if (switches == null)
+        {
+            // indicates no links are connected to the switches
+            switches = new HashSet<DatapathId>();
+            switches.add(pinSwitch);
+        }
+
+        for (DatapathId sid : switches) {
+            IOFSwitch sw = switchService.getSwitch(sid);
+            if (sw == null) continue;
+            Collection<OFPort> enabledPorts = sw.getEnabledPortNumbers();
+            if (enabledPorts == null)
+                continue;
+            Set<OFPort> ports = new HashSet<OFPort>();
+            ports.addAll(enabledPorts);
+
+            // all the ports known to topology // without tunnels.
+            // out of these, we need to choose only those that are
+            // broadcast port, otherwise, we should eliminate.
+            Set<OFPort> portsKnownToTopo = ti.getPortsWithLinks(sid);
+
+            if (portsKnownToTopo != null) {
+                for (OFPort p : portsKnownToTopo) {
+                    NodePortTuple npt =
+                            new NodePortTuple(sid, p);
+                    if (ti.isBroadcastPort(npt) == false) {
+                        ports.remove(p);
+                    }
+                }
+            }
+
+            Set<OFPort> portsToEliminate = getPortsToEliminateForBDDP(sid);
+            if (portsToEliminate != null) {
+                ports.removeAll(portsToEliminate);
+            }
+
+            // remove the incoming switch port
+            if (pinSwitch == sid) {
+                ports.remove((pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT)));
+            }
+
+            // we have all the switch ports to which we need to broadcast.
+            doMultiActionPacketOut(pi.getData(), sw, ports, cntx);
+        }
+
+    }
+
+    protected Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
+        // get the packet-in switch.
+        Ethernet eth =
+                IFloodlightProviderService.bcStore.
+                get(cntx,IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+
+        if (eth.getPayload() instanceof BSN) {
+            BSN bsn = (BSN) eth.getPayload();
+            if (bsn == null) return Command.STOP;
+            if (bsn.getPayload() == null) return Command.STOP;
+
+            // It could be a packet other than BSN LLDP, therefore
+            // continue with the regular processing.
+            if (bsn.getPayload() instanceof LLDP == false)
+                return Command.CONTINUE;
+
+            doFloodBDDP(sw.getId(), pi, cntx);
+            return Command.STOP;
+        } else {
+            return dropFilter(sw.getId(), pi, cntx);
+        }
+    }
+
+    /**
+     * Updates concerning switch disconnect and port down are not processed.
+     * LinkDiscoveryManager is expected to process those messages and send
+     * multiple link removed messages.  However, all the updates from
+     * LinkDiscoveryManager would be propagated to the listeners of topology.
+     */
+    public List<LDUpdate> applyUpdates() {
+        List<LDUpdate> appliedUpdates = new ArrayList<LDUpdate>();
+        LDUpdate update = null;
+        while (ldUpdates.peek() != null) {
+            try {
+                update = ldUpdates.take();
+            } catch (Exception e) {
+                log.error("Error reading link discovery update.", e);
+            }
+            if (log.isDebugEnabled()) {
+                log.debug("Applying update: {}", update);
+            }
+
+            switch (update.getOperation()) {
+            case LINK_UPDATED:
+                addOrUpdateLink(update.getSrc(), update.getSrcPort(),
+                        update.getDst(), update.getDstPort(),
+                        update.getLatency(), update.getType());
+                break;
+            case LINK_REMOVED:
+                removeLink(update.getSrc(), update.getSrcPort(),
+                        update.getDst(), update.getDstPort());
+                break;
+            case SWITCH_UPDATED:
+                addOrUpdateSwitch(update.getSrc());
+                break;
+            case SWITCH_REMOVED:
+                removeSwitch(update.getSrc());
+                break;
+            case TUNNEL_PORT_ADDED:
+                addTunnelPort(update.getSrc(), update.getSrcPort());
+                break;
+            case TUNNEL_PORT_REMOVED:
+                removeTunnelPort(update.getSrc(), update.getSrcPort());
+                break;
+            case PORT_UP: case PORT_DOWN:
+                break;
+            }
+            // Add to the list of applied updates.
+            appliedUpdates.add(update);
+        }
+        return (Collections.unmodifiableList(appliedUpdates));
+    }
+
+    protected void addOrUpdateSwitch(DatapathId sw) {
+        /*TODO react appropriately
 
 		addSwitch(sw);
 		for (OFPortDesc p : switchService.getSwitch(sw).getPorts()) {
 			addPortToSwitch(sw, p.getPortNo());
 		}
-		*/
-		return;
-	}
-
-	public void addTunnelPort(DatapathId sw, OFPort port) {
-		NodePortTuple npt = new NodePortTuple(sw, port);
-		tunnelPorts.add(npt);
-		tunnelPortsUpdated = true;
-	}
-
-	public void removeTunnelPort(DatapathId sw, OFPort port) {
-		NodePortTuple npt = new NodePortTuple(sw, port);
-		tunnelPorts.remove(npt);
-		tunnelPortsUpdated = true;
-	}
-
-	public boolean createNewInstance() {
-		return createNewInstance("internal");
-	}
-
-	/**
-	 * This function computes a new topology instance.
-	 * It ignores links connected to all broadcast domain ports
-	 * and tunnel ports. The method returns if a new instance of
-	 * topology was created or not.
-	 */
-	protected boolean createNewInstance(String reason) {
-		Set<NodePortTuple> blockedPorts = new HashSet<NodePortTuple>();
-
-		if (!linksUpdated) return false;
-
-		Map<NodePortTuple, Set<Link>> openflowLinks;
-		openflowLinks =
-				new HashMap<NodePortTuple, Set<Link>>();
-		Set<NodePortTuple> nptList = switchPortLinks.keySet();
-
-		if (nptList != null) {
-			for(NodePortTuple npt: nptList) {
-				Set<Link> linkSet = switchPortLinks.get(npt);
-				if (linkSet == null) continue;
-				openflowLinks.put(npt, new HashSet<Link>(linkSet));
-			}
-		}
+         */
+        return;
+    }
 
-		// Identify all broadcast domain ports.
-		// Mark any port that has inconsistent set of links
-		// as broadcast domain ports as well.
-		Set<NodePortTuple> broadcastDomainPorts =
-				identifyBroadcastDomainPorts();
-
-		// Remove all links incident on broadcast domain ports.
-		for (NodePortTuple npt : broadcastDomainPorts) {
-			if (switchPortLinks.get(npt) == null) continue;
-			for (Link link : switchPortLinks.get(npt)) {
-				removeLinkFromStructure(openflowLinks, link);
-			}
-		}
+    public void addTunnelPort(DatapathId sw, OFPort port) {
+        NodePortTuple npt = new NodePortTuple(sw, port);
+        tunnelPorts.add(npt);
+        tunnelPortsUpdated = true;
+    }
 
-		// Remove all tunnel links.
-		for (NodePortTuple npt: tunnelPorts) {
-			if (switchPortLinks.get(npt) == null) continue;
-			for (Link link : switchPortLinks.get(npt)) {
-				removeLinkFromStructure(openflowLinks, link);
-			}
-		}
-		//switchPorts contains only ports that are part of links. Calculation of broadcast ports needs set of all ports. 
-		Map<DatapathId, Set<OFPort>> allPorts = new HashMap<DatapathId, Set<OFPort>>();;
-		for (DatapathId sw : switchPorts.keySet()){
-			allPorts.put(sw, this.getPorts(sw));
-		}
+    public void removeTunnelPort(DatapathId sw, OFPort port) {
+        NodePortTuple npt = new NodePortTuple(sw, port);
+        tunnelPorts.remove(npt);
+        tunnelPortsUpdated = true;
+    }
 
-		TopologyInstance nt = new TopologyInstance(switchPorts,
-				blockedPorts,
-				openflowLinks,
-				broadcastDomainPorts,
-				tunnelPorts,
-				switchPortLinks,
-				allPorts,
-				interClusterLinks);
-
-		nt.compute();
-		
-		currentInstance = nt;
-
-		return true;
-	}
-
-	/**
-	 *  We expect every switch port to have at most two links.  Both these
-	 *  links must be unidirectional links connecting to the same switch port.
-	 *  If not, we will mark this as a broadcast domain port.
-	 */
-	protected Set<NodePortTuple> identifyBroadcastDomainPorts() {
-
-		Set<NodePortTuple> broadcastDomainPorts =
-				new HashSet<NodePortTuple>();
-		broadcastDomainPorts.addAll(this.interClusterLinks.keySet());
-
-		Set<NodePortTuple> additionalNpt =
-				new HashSet<NodePortTuple>();
-
-		// Copy switchPortLinks
-		Map<NodePortTuple, Set<Link>> spLinks =
-				new HashMap<NodePortTuple, Set<Link>>();
-		for (NodePortTuple npt : switchPortLinks.keySet()) {
-			spLinks.put(npt, new HashSet<Link>(switchPortLinks.get(npt)));
-		}
+    public boolean createNewInstance() {
+        return createNewInstance("internal");
+    }
 
-		for (NodePortTuple npt : spLinks.keySet()) {
-			Set<Link> links = spLinks.get(npt);
-			boolean bdPort = false;
-			ArrayList<Link> linkArray = new ArrayList<Link>();
-			if (links.size() > 2) {
-				bdPort = true;
-			} else if (links.size() == 2) {
-				for (Link l : links) {
-					linkArray.add(l);
-				}
-				// now, there should be two links in [0] and [1].
-				Link l1 = linkArray.get(0);
-				Link l2 = linkArray.get(1);
-
-				// check if these two are symmetric.
-				if (!l1.getSrc().equals(l2.getDst()) ||
-						!l1.getSrcPort().equals(l2.getDstPort()) ||
-						!l1.getDst().equals(l2.getSrc()) ||
-						!l1.getDstPort().equals(l2.getSrcPort())) {
-					bdPort = true;
-				}
-			}
-
-			if (bdPort && (broadcastDomainPorts.contains(npt) == false)) {
-				additionalNpt.add(npt);
-			}
-		}
+    /**
+     * This function computes a new topology instance.
+     * It ignores links connected to all broadcast domain ports
+     * and tunnel ports. The method returns if a new instance of
+     * topology was created or not.
+     */
+    protected boolean createNewInstance(String reason) {
+        Set<NodePortTuple> blockedPorts = new HashSet<NodePortTuple>();
 
-		if (additionalNpt.size() > 0) {
-			log.warn("The following switch ports have multiple " +
-					"links incident on them, so these ports will be treated " +
-					" as braodcast domain ports. {}", additionalNpt);
+        if (!linksUpdated) return false;
 
-			broadcastDomainPorts.addAll(additionalNpt);
-		}
-		return broadcastDomainPorts;
-	}
+        Map<NodePortTuple, Set<Link>> openflowLinks;
+        openflowLinks =
+                new HashMap<NodePortTuple, Set<Link>>();
+        Set<NodePortTuple> nptList = switchPortLinks.keySet();
 
+        if (nptList != null) {
+            for(NodePortTuple npt: nptList) {
+                Set<Link> linkSet = switchPortLinks.get(npt);
+                if (linkSet == null) continue;
+                openflowLinks.put(npt, new HashSet<Link>(linkSet));
+            }
+        }
 
+        // Identify all broadcast domain ports.
+        // Mark any port that has inconsistent set of links
+        // as broadcast domain ports as well.
+        Set<NodePortTuple> broadcastDomainPorts =
+                identifyBroadcastDomainPorts();
+
+        // Remove all links incident on broadcast domain ports.
+        for (NodePortTuple npt : broadcastDomainPorts) {
+            if (switchPortLinks.get(npt) == null) continue;
+            for (Link link : switchPortLinks.get(npt)) {
+                removeLinkFromStructure(openflowLinks, link);
+            }
+        }
+
+        // Remove all tunnel links.
+        for (NodePortTuple npt: tunnelPorts) {
+            if (switchPortLinks.get(npt) == null) continue;
+            for (Link link : switchPortLinks.get(npt)) {
+                removeLinkFromStructure(openflowLinks, link);
+            }
+        }
+        //switchPorts contains only ports that are part of links. Calculation of broadcast ports needs set of all ports. 
+        Map<DatapathId, Set<OFPort>> allPorts = new HashMap<DatapathId, Set<OFPort>>();;
+        for (DatapathId sw : switchPorts.keySet()){
+            allPorts.put(sw, this.getPorts(sw));
+        }
 
-	public void informListeners(List<LDUpdate> linkUpdates) {
+        TopologyInstance nt = new TopologyInstance(switchPorts,
+                blockedPorts,
+                openflowLinks,
+                broadcastDomainPorts,
+                tunnelPorts,
+                switchPortLinks,
+                allPorts,
+                interClusterLinks);
 
-		if (role != null && role != HARole.ACTIVE)
-			return;
+        nt.compute();
 
-		for(int i=0; i < topologyAware.size(); ++i) {
-			ITopologyListener listener = topologyAware.get(i);
-			listener.topologyChanged(linkUpdates);
-		}
-	}
+        currentInstance = nt;
 
-	public void addSwitch(DatapathId sid) {
-		if (switchPorts.containsKey(sid) == false) {
-			switchPorts.put(sid, new HashSet<OFPort>());
-		}
-	}
-
-	private void addPortToSwitch(DatapathId s, OFPort p) {
-		addSwitch(s);
-		switchPorts.get(s).add(p);
-	}
-
-	public void removeSwitch(DatapathId sid) {
-		// Delete all the links in the switch, switch and all
-		// associated data should be deleted.
-		if (switchPorts.containsKey(sid) == false) return;
-
-		// Check if any tunnel ports need to be removed.
-		for(NodePortTuple npt: tunnelPorts) {
-			if (npt.getNodeId() == sid) {
-				removeTunnelPort(npt.getNodeId(), npt.getPortId());
-			}
-		}
+        return true;
+    }
 
-		Set<Link> linksToRemove = new HashSet<Link>();
-		for(OFPort p: switchPorts.get(sid)) {
-			NodePortTuple n1 = new NodePortTuple(sid, p);
-			linksToRemove.addAll(switchPortLinks.get(n1));
-		}
+    /**
+     *  We expect every switch port to have at most two links.  Both these
+     *  links must be unidirectional links connecting to the same switch port.
+     *  If not, we will mark this as a broadcast domain port.
+     */
+    protected Set<NodePortTuple> identifyBroadcastDomainPorts() {
 
-		if (linksToRemove.isEmpty()) return;
+        Set<NodePortTuple> broadcastDomainPorts =
+                new HashSet<NodePortTuple>();
+        broadcastDomainPorts.addAll(this.interClusterLinks.keySet());
 
-		for(Link link: linksToRemove) {
-			removeLink(link);
-		}
-	}
-
-	/**
-	 * Add the given link to the data structure.
-	 * @param s
-	 * @param l
-	 */
-	private void addLinkToStructure(Map<NodePortTuple, Set<Link>> s, Link l) {
-		NodePortTuple n1 = new NodePortTuple(l.getSrc(), l.getSrcPort());
-		NodePortTuple n2 = new NodePortTuple(l.getDst(), l.getDstPort());
-
-		if (s.get(n1) == null) {
-			s.put(n1, new HashSet<Link>());
-		} 
-		if (s.get(n2) == null) {
-			s.put(n2, new HashSet<Link>());
-		}
+        Set<NodePortTuple> additionalNpt =
+                new HashSet<NodePortTuple>();
 
-		/* 
-		 * Since we don't include latency in .equals(), we need
-		 * to explicitly remove the existing link (if present).
-		 * Otherwise, new latency values for existing links will
-		 * never be accepted.
-		 */
+        // Copy switchPortLinks
+        Map<NodePortTuple, Set<Link>> spLinks =
+                new HashMap<NodePortTuple, Set<Link>>();
+        for (NodePortTuple npt : switchPortLinks.keySet()) {
+            spLinks.put(npt, new HashSet<Link>(switchPortLinks.get(npt)));
+        }
+
+        for (NodePortTuple npt : spLinks.keySet()) {
+            Set<Link> links = spLinks.get(npt);
+            boolean bdPort = false;
+            ArrayList<Link> linkArray = new ArrayList<Link>();
+            if (links.size() > 2) {
+                bdPort = true;
+            } else if (links.size() == 2) {
+                for (Link l : links) {
+                    linkArray.add(l);
+                }
+                // now, there should be two links in [0] and [1].
+                Link l1 = linkArray.get(0);
+                Link l2 = linkArray.get(1);
+
+                // check if these two are symmetric.
+                if (!l1.getSrc().equals(l2.getDst()) ||
+                        !l1.getSrcPort().equals(l2.getDstPort()) ||
+                        !l1.getDst().equals(l2.getSrc()) ||
+                        !l1.getDstPort().equals(l2.getSrcPort())) {
+                    bdPort = true;
+                }
+            }
+
+            if (bdPort && (broadcastDomainPorts.contains(npt) == false)) {
+                additionalNpt.add(npt);
+            }
+        }
+
+        if (additionalNpt.size() > 0) {
+            log.warn("The following switch ports have multiple " +
+                    "links incident on them, so these ports will be treated " +
+                    " as braodcast domain ports. {}", additionalNpt);
+
+            broadcastDomainPorts.addAll(additionalNpt);
+        }
+        return broadcastDomainPorts;
+    }
+
+
+
+    public void informListeners(List<LDUpdate> linkUpdates) {
+
+        if (role != null && role != HARole.ACTIVE)
+            return;
+
+        for(int i=0; i < topologyAware.size(); ++i) {
+            ITopologyListener listener = topologyAware.get(i);
+            listener.topologyChanged(linkUpdates);
+        }
+    }
+
+    public void addSwitch(DatapathId sid) {
+        if (switchPorts.containsKey(sid) == false) {
+            switchPorts.put(sid, new HashSet<OFPort>());
+        }
+    }
+
+    private void addPortToSwitch(DatapathId s, OFPort p) {
+        addSwitch(s);
+        switchPorts.get(s).add(p);
+    }
+
+    public void removeSwitch(DatapathId sid) {
+        // Delete all the links in the switch, switch and all
+        // associated data should be deleted.
+        if (switchPorts.containsKey(sid) == false) return;
+
+        // Check if any tunnel ports need to be removed.
+        for(NodePortTuple npt: tunnelPorts) {
+            if (npt.getNodeId() == sid) {
+                removeTunnelPort(npt.getNodeId(), npt.getPortId());
+            }
+        }
+
+        Set<Link> linksToRemove = new HashSet<Link>();
+        for(OFPort p: switchPorts.get(sid)) {
+            NodePortTuple n1 = new NodePortTuple(sid, p);
+            linksToRemove.addAll(switchPortLinks.get(n1));
+        }
+
+        if (linksToRemove.isEmpty()) return;
+
+        for(Link link: linksToRemove) {
+            removeLink(link);
+        }
+    }
+
+    /**
+     * Add the given link to the data structure.
+     * @param s
+     * @param l
+     */
+    private void addLinkToStructure(Map<NodePortTuple, Set<Link>> s, Link l) {
+        NodePortTuple n1 = new NodePortTuple(l.getSrc(), l.getSrcPort());
+        NodePortTuple n2 = new NodePortTuple(l.getDst(), l.getDstPort());
+
+        if (s.get(n1) == null) {
+            s.put(n1, new HashSet<Link>());
+        } 
+        if (s.get(n2) == null) {
+            s.put(n2, new HashSet<Link>());
+        }
+
+        /* 
+         * Since we don't include latency in .equals(), we need
+         * to explicitly remove the existing link (if present).
+         * Otherwise, new latency values for existing links will
+         * never be accepted.
+         */
         s.get(n1).remove(l);
         s.get(n2).remove(l);
         s.get(n1).add(l);
@@ -1202,12 +1166,12 @@ public class TopologyManager implements IFloodlightModule, ITopologyService, IRo
     }
 
     protected void addOrUpdateTunnelLink(DatapathId srcId, OFPort srcPort, DatapathId dstId,
-                                         OFPort dstPort, U64 latency) {
+            OFPort dstPort, U64 latency) {
         // If you need to handle tunnel links, this is a placeholder.
     }
 
     public void addOrUpdateLink(DatapathId srcId, OFPort srcPort, DatapathId dstId,
-                                OFPort dstPort, U64 latency, LinkType type) {
+            OFPort dstPort, U64 latency, LinkType type) {
         Link link = new Link(srcId, srcPort, dstId, dstPort, latency);
 
         if (type.equals(LinkType.MULTIHOP_LINK)) {
@@ -1265,7 +1229,7 @@ public class TopologyManager implements IFloodlightModule, ITopologyService, IRo
     }
 
     public void removeLink(DatapathId srcId, OFPort srcPort,
-                           DatapathId dstId, OFPort dstPort) {
+            DatapathId dstId, OFPort dstPort) {
         Link link = new Link(srcId, srcPort, dstId, dstPort, U64.ZERO /* does not matter for remove (not included in .equals() of Link) */);
         removeLink(link);
     }
@@ -1354,4 +1318,9 @@ public class TopologyManager implements IFloodlightModule, ITopologyService, IRo
         TopologyInstance ti = getCurrentInstance();
         return ti.getArchipelagoIds();
     }
+
+    @Override
+    public TopologyInstance getCurrentTopologyInstance() {
+        return getCurrentInstance();
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
index afe5df42bea3680014f0bf5545303d95159820b5..0d0986e8735e9ece98eab72fcd63a6aec41d9c5f 100644
--- a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
+++ b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
@@ -34,7 +34,9 @@ import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.debugcounter.MockDebugCounterService;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.floodlightcontroller.routing.IRoutingService;
 import net.floodlightcontroller.routing.Route;
+import net.floodlightcontroller.routing.RoutingManager;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.core.types.NodePortTuple;
 import net.floodlightcontroller.topology.TopologyInstance;
@@ -52,6 +54,7 @@ import org.slf4j.LoggerFactory;
 public class TopologyInstanceTest {
     protected static Logger log = LoggerFactory.getLogger(TopologyInstanceTest.class);
     protected TopologyManager topologyManager;
+    protected RoutingManager routingManager;
     protected FloodlightModuleContext fmc;
     protected ILinkDiscoveryService linkDiscovery;
     protected MockFloodlightProvider mockFloodlightProvider;
@@ -71,8 +74,13 @@ public class TopologyInstanceTest {
         fmc.addService(IDebugCounterService.class, new MockDebugCounterService());
         MockThreadPoolService tp = new MockThreadPoolService();
         topologyManager = new TopologyManager();
+        routingManager = new RoutingManager();
+        fmc.addService(IRoutingService.class, routingManager);
         fmc.addService(IThreadPoolService.class, tp);
+        fmc.addService(ITopologyService.class, topologyManager);
         topologyManager.init(fmc);
+        routingManager.init(fmc);
+        routingManager.startUp(fmc);
         tp.init(fmc);
         tp.startUp(fmc);
     }
@@ -691,7 +699,7 @@ public class TopologyInstanceTest {
          */
         topologyManager.setPathMetric(LATENCY);
         configureTopology(linkArray, lat);
-        List<Route> lat_paths = topologyManager.getPathsFast(one, three, k);
+        List<Route> lat_paths = routingManager.getPathsFast(one, three, k);
         log.info("Path 1: {}", lat_paths.get(0));
         log.info("Path 2: {}", lat_paths.get(1));
 
@@ -700,7 +708,7 @@ public class TopologyInstanceTest {
         topologyManager.setPathMetric(HOPCOUNT);
         configureTopology(linkArray, lat);
         topologyManager.createNewInstance();
-        List<Route> hop_paths = topologyManager.getPathsFast(one, three, k);
+        List<Route> hop_paths = routingManager.getPathsFast(one, three, k);
         log.info("Path 1: {}", hop_paths.get(0));
         log.info("Path 2: {}", hop_paths.get(1));
 
@@ -712,7 +720,7 @@ public class TopologyInstanceTest {
         int [] lat1 = {1,50,1};
         configureTopology(linkArray, lat1);
         topologyManager.createNewInstance();
-        List<Route> r1 = topologyManager.getPathsFast(one, three, k);
+        List<Route> r1 = routingManager.getPathsFast(one, three, k);
         assertTrue((r1.get(0)).equals(lat_paths.get(0)));
         assertTrue((r1.get(1)).equals(lat_paths.get(1)));
 
@@ -776,7 +784,7 @@ public class TopologyInstanceTest {
         int [] lat4 = {3,2,4,2,1,1,2,3,2};
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r = topologyManager.getPathsFast(one, six, k);
+        List<Route> r = routingManager.getPathsFast(one, six, k);
         for(int i = 0; i< r.size(); i++) {
             log.info("k = (1000) => Route: {}", r.get(i));
         }
@@ -792,7 +800,7 @@ public class TopologyInstanceTest {
         k = 7;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r2 = topologyManager.getPathsFast(one, six, k);
+        List<Route> r2 = routingManager.getPathsFast(one, six, k);
         for(int i = 0; i< r2.size(); i++) {
             log.info("k = (7) => Route: {}", r2.get(i));
         }
@@ -808,7 +816,7 @@ public class TopologyInstanceTest {
         k = -1;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r3 = topologyManager.getPathsFast(one, six, k);
+        List<Route> r3 = routingManager.getPathsFast(one, six, k);
         for(int i = 0; i< r3.size(); i++) {
             log.info("HOPCOUNT.k = (-1) => Route: {}", r3.get(i));
         }
@@ -824,7 +832,7 @@ public class TopologyInstanceTest {
         k = -1;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r4 = topologyManager.getPathsFast(one, six, k);
+        List<Route> r4 = routingManager.getPathsFast(one, six, k);
         for(int i = 0; i< r4.size(); i++) {
             log.info("LATENCY.k = (-1) => Route: {}", r4.get(i));
         }
@@ -840,7 +848,7 @@ public class TopologyInstanceTest {
         k = 3;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r5 = topologyManager.getPathsFast(one, six, k);
+        List<Route> r5 = routingManager.getPathsFast(one, six, k);
         for(int i = 0; i< r5.size(); i++) {
             log.info("HOPCOUNT.k = (3) => Route: {}", r5.get(i));
         }
@@ -856,7 +864,7 @@ public class TopologyInstanceTest {
         k = 4;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r6 = topologyManager.getPathsFast(one, six, k);
+        List<Route> r6 = routingManager.getPathsFast(one, six, k);
         for(int i = 0; i< r6.size(); i++) {
             log.info("LATENCY.k = (4) => Route: {}", r6.get(i));
         }
@@ -873,7 +881,7 @@ public class TopologyInstanceTest {
         int [] lat5 = {0,0,0,0,0,0,0,0,0};
         configureTopology(linkArray2, lat5);
         topologyManager.createNewInstance();
-        List<Route> r7 = topologyManager.getPathsFast(one, six, k);
+        List<Route> r7 = routingManager.getPathsFast(one, six, k);
         for(int i = 0; i< r7.size(); i++) {
             log.info("Route latency all ZERO: {}", r7.get(i));
         }
@@ -888,7 +896,7 @@ public class TopologyInstanceTest {
         k = 4;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r8 = topologyManager.getPathsFast(one, one, k);
+        List<Route> r8 = routingManager.getPathsFast(one, one, k);
         for(int i = 0; i< r8.size(); i++) {
             log.info("(src == dst) => Route: {}", r8.get(i));
         }
@@ -903,7 +911,7 @@ public class TopologyInstanceTest {
         k = 4;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r9 = topologyManager.getPathsFast(six, one, k);
+        List<Route> r9 = routingManager.getPathsFast(six, one, k);
         for(int i = 0; i< r9.size(); i++) {
             log.info("Reversed Route (6 -> 1): {}", r9.get(i));
         }
@@ -919,7 +927,7 @@ public class TopologyInstanceTest {
         k = 4;
         configureTopology(linkArray2, lat4);
         topologyManager.createNewInstance();
-        List<Route> r10 = topologyManager.getPathsFast(one, DatapathId.of(7), k);
+        List<Route> r10 = routingManager.getPathsFast(one, DatapathId.of(7), k);
         for(int i = 0; i< r10.size(); i++) {
             log.info("(src == 7) => Route: {}", r10.get(i));
         }