diff --git a/src/main/java/net/floodlightcontroller/topology/Archipelago.java b/src/main/java/net/floodlightcontroller/topology/Archipelago.java
index 7b80fd614179dfd966ef0e737e0db0ec23ac048c..9a8f8c98ceb94609c42280984457bf45ca950b03 100644
--- a/src/main/java/net/floodlightcontroller/topology/Archipelago.java
+++ b/src/main/java/net/floodlightcontroller/topology/Archipelago.java
@@ -54,6 +54,16 @@ public class Archipelago {
             id = a.getId();
         }
     }
+    
+    Set<DatapathId> getSwitches() {
+        Set<DatapathId> allSwitches = new HashSet<DatapathId>();
+        for (Cluster c : clusters) {
+            for (DatapathId d : c.getNodes()) {
+                allSwitches.add(d);
+            }
+        }
+        return allSwitches;
+    }
 
     BroadcastTree getBroadcastTree() {
         return destinationRootedFullTree;
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
index 56748607a4dd4dd404022218e0a6c75b52d08206..ad88dd6859506f53448d60270e7b3249e8649066 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
@@ -30,6 +30,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.*;
+import java.util.Map.Entry;
 
 /**
  * A representation of a network topology. Used internally by
@@ -56,7 +57,7 @@ public class TopologyInstance {
     private Map<NodePortTuple, Set<Link>> switchPortLinks; // Set of links organized by node port tuple
     /** Set of links that are blocked. */
     private Set<Link> blockedLinks;
-  
+
     private Set<DatapathId> switches;
     private Set<NodePortTuple> broadcastDomainPorts;
     private Set<NodePortTuple> tunnelPorts;
@@ -66,47 +67,49 @@ public class TopologyInstance {
 
     // States for routing
     private Map<DatapathId, BroadcastTree> destinationRootedTrees;
-  
+
     private Map<DatapathId, Set<NodePortTuple>> clusterPorts;
     private Map<DatapathId, BroadcastTree> clusterBroadcastTrees;
- 
+
     private Map<DatapathId, Set<NodePortTuple>> clusterBroadcastNodePorts;
-	//Set of NodePortTuples of the finiteBroadcastTree
+    //Set of NodePortTuples of the finiteBroadcastTree
     private Set<NodePortTuple> broadcastNodePorts;  
-	//destinationRootedTrees over whole topology (not only intra-cluster tree)
+    //destinationRootedTrees over whole topology (not only intra-cluster tree)
     private Map<DatapathId, BroadcastTree> destinationRootedFullTrees;
-	//Set of all links organized by node port tuple. Note that switchPortLinks does not contain all links of multi-cluster topology.
+    //Set of all links organized by node port tuple. Note that switchPortLinks does not contain all links of multi-cluster topology.
     private Map<NodePortTuple, Set<Link>> allLinks;
-	//Set of all ports organized by DatapathId. Note that switchPorts map contains only ports with links.
-	private Map<DatapathId, Set<OFPort>> allPorts;
+    //Set of all ports organized by DatapathId. Note that switchPorts map contains only ports with links.
+    private Map<DatapathId, Set<OFPort>> allPorts;
     //Set of all the inter-island or "external" links. Also known as portBroadcastDomainLinks in TopologyManager.
     private Map<NodePortTuple, Set<Link>> externalLinks;
-	// Maps broadcast ports to DatapathId
+    // Maps broadcast ports to DatapathId
     private Map<DatapathId, Set<OFPort>> broadcastPortMap;
 
     private Set<Archipelago> archipelagos;
     
+    private Set<Link> nonExternalInterClusterLinks;
+
     // pathcache contains n (specified in floodlightdefault.properties) routes
     // in order between every switch. Calculated using Yen's algorithm.
     private Map<RouteId, List<Route>> pathcache;
 
     protected TopologyInstance(Map<DatapathId, Set<OFPort>> switchPorts,
-                            Set<NodePortTuple> blockedPorts,
-                            Map<NodePortTuple, Set<Link>> switchPortLinks,
-                            Set<NodePortTuple> broadcastDomainPorts,
-                            Set<NodePortTuple> tunnelPorts, 
-                            Map<NodePortTuple, Set<Link>> allLinks,
-                            Map<DatapathId, Set<OFPort>> allPorts,
-                            Map<NodePortTuple, Set<Link>> externalLinks) {
-	
+            Set<NodePortTuple> blockedPorts,
+            Map<NodePortTuple, Set<Link>> switchPortLinks,
+            Set<NodePortTuple> broadcastDomainPorts,
+            Set<NodePortTuple> tunnelPorts, 
+            Map<NodePortTuple, Set<Link>> allLinks,
+            Map<DatapathId, Set<OFPort>> allPorts,
+            Map<NodePortTuple, Set<Link>> externalLinks) {
+
         this.switches = new HashSet<DatapathId>(switchPorts.keySet());
         this.switchPorts = new HashMap<DatapathId, Set<OFPort>>();
         for (DatapathId sw : switchPorts.keySet()) {
             this.switchPorts.put(sw, new HashSet<OFPort>(switchPorts.get(sw)));
         }
-		
-		this.allPorts = new HashMap<DatapathId, Set<OFPort>>();
-		for (DatapathId sw : allPorts.keySet()) {
+
+        this.allPorts = new HashMap<DatapathId, Set<OFPort>>();
+        for (DatapathId sw : allPorts.keySet()) {
             this.allPorts.put(sw, new HashSet<OFPort>(allPorts.get(sw)));
         }
 
@@ -115,8 +118,8 @@ public class TopologyInstance {
         for (NodePortTuple npt : switchPortLinks.keySet()) {
             this.switchPortLinks.put(npt, new HashSet<Link>(switchPortLinks.get(npt)));
         }
-        
-		this.allLinks = new HashMap<NodePortTuple, Set<Link>>();
+
+        this.allLinks = new HashMap<NodePortTuple, Set<Link>>();
         for (NodePortTuple npt : allLinks.keySet()) {
             this.allLinks.put(npt, new HashSet<Link>(allLinks.get(npt)));
         }
@@ -126,25 +129,26 @@ public class TopologyInstance {
             this.externalLinks.put(npt, new HashSet<Link>(externalLinks.get(npt)));
         }
 
+        this.nonExternalInterClusterLinks = new HashSet<Link>();
         this.archipelagos = new HashSet<Archipelago>();
-        
+
         this.broadcastDomainPorts = new HashSet<NodePortTuple>(broadcastDomainPorts);
         this.tunnelPorts = new HashSet<NodePortTuple>(tunnelPorts);
 
         this.blockedLinks = new HashSet<Link>();
-       
+
         this.clusters = new HashSet<Cluster>();
         this.switchClusterMap = new HashMap<DatapathId, Cluster>();
         this.destinationRootedTrees = new HashMap<DatapathId, BroadcastTree>();
         this.destinationRootedFullTrees= new HashMap<DatapathId, BroadcastTree>();
-		this.broadcastNodePorts= new HashSet<NodePortTuple>();
-		this.broadcastPortMap = new HashMap<DatapathId,Set<OFPort>>();
+        this.broadcastNodePorts= new HashSet<NodePortTuple>();
+        this.broadcastPortMap = new HashMap<DatapathId,Set<OFPort>>();
         this.clusterBroadcastTrees = new HashMap<DatapathId, BroadcastTree>();
         this.clusterBroadcastNodePorts = new HashMap<DatapathId, Set<NodePortTuple>>();
 
         this.pathcache = new HashMap<RouteId, List<Route>>();
     }
-	
+
     protected void compute() {
         // Step 1: Compute clusters ignoring broadcast domain links
         // Create nodes for clusters in the higher level topology
@@ -155,33 +159,34 @@ public class TopologyInstance {
         // Avoid adding blocked links
         // Remaining links are inter-cluster links
         addIntraClusterLinks();
-        
+
         // Step 1.2 Compute the archipelagos (def: group of clusters). Each archipelago
         // will have its own finiteBroadcastTree, which will be randomly chosen. This is
         // because each achipelago is by definition isolated from all other archipelagos.
         // The broadcast tree will not be set for each archipelago until after all paths
         // have been computed. This is so we don't run dijkstras redundantly
         calculateArchipelagos();
-        
+
         // Step 2. Compute shortest path trees in each cluster for
         // unicast routing.  The trees are rooted at the destination.
         // Cost for tunnel links and direct links are the same.
         calculateShortestPathTreeInClusters();
-        
+
         // Step 3. Compute broadcast tree in each cluster.
         // Cost for tunnel links are high to discourage use of
         // tunnel links.  The cost is set to the number of nodes
         // in the cluster + 1, to use as minimum number of
         // clusters as possible.
         calculateBroadcastNodePortsInClusters();
-        
+
         // Step 4. Compute e2e shortest path trees on entire topology for unicast routing.
         // The trees are rooted at the destination.
         // Cost for tunnel links and direct links are the same.
         calculateAllShortestPaths();
-        
-        selectBroadcastTreeForEachArchipelago();
-        
+
+        // Step 4.1 Use Yens algorithm to compute multiple paths 
+        computeOrderedPaths();
+
         // Step 5. Determine broadcast switch ports for each archipelago
         computeBcastNPTsFromArchipelagos();
 
@@ -189,55 +194,52 @@ public class TopologyInstance {
         // Edge ports included
         computeBcastPortsPerSwitchFromBcastNTPs();
 
-        // Step 4.5 Use Yens algorithm to compute multiple paths 
-        computeOrderedPaths();
-       	
         // Step 7. print topology.
         printTopology();
     }
 
-	/*
-	 * Checks if OF port is edge port
-	 */
+    /*
+     * Checks if OF port is edge port
+     */
     protected boolean isEdge(DatapathId sw, OFPort portId) { 
-		NodePortTuple np = new NodePortTuple(sw, portId);
-		if (allLinks.get(np) == null || allLinks.get(np).isEmpty()) {
-			return true;
-		}
-		else {
-			return false;
-		}
+        NodePortTuple np = new NodePortTuple(sw, portId);
+        if (allLinks.get(np) == null || allLinks.get(np).isEmpty()) {
+            return true;
+        }
+        else {
+            return false;
+        }
     }   
 
-	/*
-	 * Returns broadcast ports for the given DatapathId
-	 */
+    /*
+     * Returns broadcast ports for the given DatapathId
+     */
     protected Set<OFPort> swBroadcastPorts(DatapathId sw) {
-    	if (!broadcastPortMap.containsKey(sw) || broadcastPortMap.get(sw) == null) {
-    		log.debug("Could not locate broadcast ports for switch {}", sw);
-    		return Collections.emptySet();
-    	} else {
-    		if (log.isDebugEnabled()) {
-    			log.debug("Found broadcast ports {} for switch {}", broadcastPortMap.get(sw), sw);
-    		}
-    		return broadcastPortMap.get(sw);
-    	}
+        if (!broadcastPortMap.containsKey(sw) || broadcastPortMap.get(sw) == null) {
+            log.debug("Could not locate broadcast ports for switch {}", sw);
+            return Collections.emptySet();
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("Found broadcast ports {} for switch {}", broadcastPortMap.get(sw), sw);
+            }
+            return broadcastPortMap.get(sw);
+        }
     }
 
     private void printTopology() {
-        log.debug("-----------------Topology-----------------------");
-        log.debug("All Links: {}", allLinks);
-		log.debug("Cluser Broadcast Trees: {}", clusterBroadcastTrees);
-        log.debug("Cluster Ports: {}", clusterPorts);
-        log.debug("Tunnel Ports: {}", tunnelPorts);
-        log.debug("Clusters: {}", clusters);
-        log.debug("Destination Rooted Full Trees: {}", destinationRootedFullTrees);
-        log.debug("Cluser Broadcast Node Ports: {}", clusterBroadcastNodePorts);
-        log.debug("Broadcast Ports Per Node (!!): {}", broadcastPortMap);
-        log.debug("Broadcast Domain Ports: {}", broadcastDomainPorts);
-        log.debug("Broadcast Node Ports: {}", broadcastDomainPorts);
-        log.debug("Archipelagos: {}", archipelagos);
-        log.debug("-----------------------------------------------");  
+        log.info("-----------------Topology-----------------------");
+        log.info("All Links: {}", allLinks);
+        log.info("Cluser Broadcast Trees: {}", clusterBroadcastTrees);
+        log.info("Cluster Ports: {}", clusterPorts);
+        log.info("Tunnel Ports: {}", tunnelPorts);
+        log.info("Clusters: {}", clusters);
+        log.info("Destination Rooted Full Trees: {}", destinationRootedFullTrees);
+        log.info("Cluser Broadcast Node Ports: {}", clusterBroadcastNodePorts);
+        log.info("Broadcast Ports Per Node (!!): {}", broadcastPortMap);
+        log.info("Broadcast Domain Ports: {}", broadcastDomainPorts);
+        log.info("Broadcast Node Ports: {}", broadcastDomainPorts);
+        log.info("Archipelagos: {}", archipelagos);
+        log.info("-----------------------------------------------");  
     }
 
     private void addIntraClusterLinks() {
@@ -254,6 +256,8 @@ public class TopologyInstance {
                     Cluster c2 = switchClusterMap.get(l.getDst());
                     if (c1 == c2) {
                         c1.addLink(l); /* link is within cluster */
+                    } else {
+                        nonExternalInterClusterLinks.add(l);
                     }
                 }
             }
@@ -283,7 +287,7 @@ public class TopologyInstance {
             ClusterDFS cdfs = new ClusterDFS();
             dfsList.put(key, cdfs);
         }
-        
+
         Set<DatapathId> currSet = new HashSet<DatapathId>();
 
         for (DatapathId sw : switches) {
@@ -325,7 +329,7 @@ public class TopologyInstance {
      * @return long: DSF index to be used when a new node is visited
      */
     private long dfsTraverse (long parentIndex, long currIndex, DatapathId currSw,
-                              Map<DatapathId, ClusterDFS> dfsList, Set<DatapathId> currSet) {
+            Map<DatapathId, ClusterDFS> dfsList, Set<DatapathId> currSet) {
 
         //Get the DFS object corresponding to the current switch
         ClusterDFS currDFS = dfsList.get(currSw);
@@ -371,9 +375,9 @@ public class TopologyInstance {
                     } else if (!dstDFS.isVisited()) {
                         // make a DFS visit
                         currIndex = dfsTraverse(
-                        		currDFS.getDfsIndex(), 
-                        		currIndex, dstSw, 
-                        		dfsList, myCurrSet);
+                                currDFS.getDfsIndex(), 
+                                currIndex, dstSw, 
+                                dfsList, myCurrSet);
 
                         if (currIndex < 0) return -1;
 
@@ -506,7 +510,7 @@ public class TopologyInstance {
         @Override
         public int hashCode() {
             assert false : "hashCode not designed";
-            return 42;
+        return 42;
         }
 
         private TopologyInstance getOuterType() {
@@ -514,11 +518,11 @@ public class TopologyInstance {
         }
     }
 
-	//calculates the broadcast tree in cluster. Old version of code.
+    //calculates the broadcast tree in cluster. Old version of code.
     private BroadcastTree clusterDijkstra(Cluster c, DatapathId root,
-                                     Map<Link, Integer> linkCost,
-                                     boolean isDstRooted) {
-    	
+            Map<Link, Integer> linkCost,
+            boolean isDstRooted) {
+
         HashMap<DatapathId, Link> nexthoplinks = new HashMap<DatapathId, Link>();
         HashMap<DatapathId, Integer> cost = new HashMap<DatapathId, Integer>();
         int w;
@@ -530,27 +534,27 @@ public class TopologyInstance {
 
         HashMap<DatapathId, Boolean> seen = new HashMap<DatapathId, Boolean>();
         PriorityQueue<NodeDist> nodeq = new PriorityQueue<NodeDist>();
-        
+
         nodeq.add(new NodeDist(root, 0));
         cost.put(root, 0);
-        
+
         while (nodeq.peek() != null) {
             NodeDist n = nodeq.poll();
             DatapathId cnode = n.getNode();
-            
+
             int cdist = n.getDist();
             if (cdist >= MAX_PATH_WEIGHT) break;
             if (seen.containsKey(cnode)) continue;
-            
+
             seen.put(cnode, true);
 
             for (Link link : c.links.get(cnode)) {
                 DatapathId neighbor;
 
                 if (isDstRooted == true) {
-                	neighbor = link.getSrc();
+                    neighbor = link.getSrc();
                 } else {
-                	neighbor = link.getDst();
+                    neighbor = link.getDst();
                 }
 
                 // links directed toward cnode will result in this condition
@@ -559,16 +563,16 @@ public class TopologyInstance {
                 if (seen.containsKey(neighbor)) continue;
 
                 if (linkCost == null || linkCost.get(link) == null) {
-                	w = 1;
+                    w = 1;
                 } else {
-                	w = linkCost.get(link);
+                    w = linkCost.get(link);
                 }
 
                 int ndist = cdist + w; // the weight of the link, always 1 in current version of floodlight.
                 if (ndist < cost.get(neighbor)) {
                     cost.put(neighbor, ndist);
                     nexthoplinks.put(neighbor, link);
-                    
+
                     NodeDist ndTemp = new NodeDist(neighbor, ndist);
                     // Remove an object that's already in there.
                     // Note that the comparison is based on only the node id,
@@ -596,12 +600,13 @@ public class TopologyInstance {
         for (Set<Link> linkset : externalLinks.values()) {
             links.addAll(linkset);
         }
-        
+        links.addAll(nonExternalInterClusterLinks);
+
         /* Base case of 1:1 mapping b/t clusters and archipelagos */
         if (links.isEmpty()) {
-        	if (!clusters.isEmpty()) {
-        		clusters.forEach(c -> archipelagos.add(new Archipelago().add(c)));
-        	}
+            if (!clusters.isEmpty()) {
+                clusters.forEach(c -> archipelagos.add(new Archipelago().add(c)));
+            }
         } else { /* Only for two or more adjacent clusters that form archipelagos */
             for (Link l : links) {
                 for (Cluster c : clusters) {
@@ -642,25 +647,13 @@ public class TopologyInstance {
             }
         }
     }
-    
-    private void selectBroadcastTreeForEachArchipelago() {    
-        // Choose a broadcast tree for each archipelago
-        for (Archipelago a : archipelagos) {
-            for (DatapathId id : destinationRootedFullTrees.keySet()) {
-                if (a.isMember(id)) {
-                    a.setBroadcastTree(destinationRootedFullTrees.get(id));
-                    break;
-                }
-            }
-        }
-    }
-    
-	/*
-	 * Dijkstra that calculates destination rooted trees over the entire topology.
-	*/
+
+    /*
+     * Dijkstra that calculates destination rooted trees over the entire topology.
+     */
     private BroadcastTree dijkstra(Map<DatapathId, Set<Link>> links, DatapathId root,
-                                     Map<Link, Integer> linkCost,
-                                     boolean isDstRooted) {
+            Map<Link, Integer> linkCost,
+            boolean isDstRooted) {
         HashMap<DatapathId, Link> nexthoplinks = new HashMap<DatapathId, Link>();
         HashMap<DatapathId, Integer> cost = new HashMap<DatapathId, Integer>();
         int w;
@@ -710,9 +703,9 @@ public class TopologyInstance {
                 }
 
                 int ndist = cdist + w; // the weight of the link, always 1 in current version of floodlight.
-                log.info("Neighbor: {}", neighbor);
-                log.info("Cost: {}", cost);
-                log.info("Neighbor cost: {}", cost.get(neighbor));
+                log.debug("Neighbor: {}", neighbor);
+                log.debug("Cost: {}", cost);
+                log.debug("Neighbor cost: {}", cost.get(neighbor));
 
                 if (!cost.containsKey(neighbor) || ndist < cost.get(neighbor)) {
                     cost.put(neighbor, ndist);
@@ -735,117 +728,117 @@ public class TopologyInstance {
     }
 
     /*
-	 * Creates a map of links and the cost associated with each link
-	 */
+     * Creates a map of links and the cost associated with each link
+     */
     protected Map<Link,Integer> initLinkCostMap() {
         Map<Link, Integer> linkCost = new HashMap<Link, Integer>();
         long rawLinkSpeed;
         int linkSpeedMBps;
         int tunnel_weight = switchPorts.size() + 1;
 
-    		/* pathMetrics:
-        	 *  1: Hop Count (Default Metrics)
-         	 *  2: Hop Count (Treat Tunnels same as link)
-         	 *  3: Latency
-         	 *  4: Link Speed
-         	*/
+        /* pathMetrics:
+         *  1: Hop Count (Default Metrics)
+         *  2: Hop Count (Treat Tunnels same as link)
+         *  3: Latency
+         *  4: Link Speed
+         */
         switch (TopologyManager.getPathMetricInternal()){
-            case HOPCOUNT_AVOID_TUNNELS:
-                if(TopologyManager.collectStatistics == true){
-                    TopologyManager.statisticsService.collectStatistics(false);
-                    TopologyManager.collectStatistics = false;
-                }
-                log.debug("Using Default: Hop Count with Tunnel Bias for Metrics");
-                for (NodePortTuple npt : tunnelPorts) {
-                    if (allLinks.get(npt) == null) continue;
-                    for (Link link : allLinks.get(npt)) {
-                        if (link == null) continue;
-                        linkCost.put(link, tunnel_weight);
-                    }
+        case HOPCOUNT_AVOID_TUNNELS:
+            if(TopologyManager.collectStatistics == true){
+                TopologyManager.statisticsService.collectStatistics(false);
+                TopologyManager.collectStatistics = false;
+            }
+            log.debug("Using Default: Hop Count with Tunnel Bias for Metrics");
+            for (NodePortTuple npt : tunnelPorts) {
+                if (allLinks.get(npt) == null) continue;
+                for (Link link : allLinks.get(npt)) {
+                    if (link == null) continue;
+                    linkCost.put(link, tunnel_weight);
                 }
-                return linkCost;
+            }
+            return linkCost;
 
-            case HOPCOUNT:
-                if(TopologyManager.collectStatistics == true){
-                    TopologyManager.statisticsService.collectStatistics(false);
-                    TopologyManager.collectStatistics = false;
-                }
-                log.debug("Using Hop Count without Tunnel Bias for Metrics");
-                for (NodePortTuple npt : allLinks.keySet()) {
-                    if (allLinks.get(npt) == null) continue;
-                    for (Link link : allLinks.get(npt)) {
-                        if (link == null) continue;
-                        linkCost.put(link,1);
-                    }
+        case HOPCOUNT:
+            if(TopologyManager.collectStatistics == true){
+                TopologyManager.statisticsService.collectStatistics(false);
+                TopologyManager.collectStatistics = false;
+            }
+            log.debug("Using Hop Count without Tunnel Bias for Metrics");
+            for (NodePortTuple npt : allLinks.keySet()) {
+                if (allLinks.get(npt) == null) continue;
+                for (Link link : allLinks.get(npt)) {
+                    if (link == null) continue;
+                    linkCost.put(link,1);
                 }
-                return linkCost;
+            }
+            return linkCost;
 
-            case LATENCY:
-                if(TopologyManager.collectStatistics == true){
-                    TopologyManager.statisticsService.collectStatistics(false);
-                    TopologyManager.collectStatistics = false;
-                }
-                log.debug("Using Latency for Route Metrics");
-                for (NodePortTuple npt : allLinks.keySet()) {
-                    if (allLinks.get(npt) == null) continue;
-                    for (Link link : allLinks.get(npt)) {
-                        if (link == null) continue;
-                        if((int)link.getLatency().getValue() < 0 || (int)link.getLatency().getValue() > MAX_LINK_WEIGHT)
-                            linkCost.put(link, MAX_LINK_WEIGHT);
-                        else
-                            linkCost.put(link,(int)link.getLatency().getValue());
-                    }
+        case LATENCY:
+            if(TopologyManager.collectStatistics == true){
+                TopologyManager.statisticsService.collectStatistics(false);
+                TopologyManager.collectStatistics = false;
+            }
+            log.debug("Using Latency for Route Metrics");
+            for (NodePortTuple npt : allLinks.keySet()) {
+                if (allLinks.get(npt) == null) continue;
+                for (Link link : allLinks.get(npt)) {
+                    if (link == null) continue;
+                    if((int)link.getLatency().getValue() < 0 || (int)link.getLatency().getValue() > MAX_LINK_WEIGHT)
+                        linkCost.put(link, MAX_LINK_WEIGHT);
+                    else
+                        linkCost.put(link,(int)link.getLatency().getValue());
                 }
-                return linkCost;
+            }
+            return linkCost;
 
-            case LINK_SPEED:
-                if(TopologyManager.collectStatistics == false){
-                    TopologyManager.statisticsService.collectStatistics(true);
-                    TopologyManager.collectStatistics = true;
-                }
-                log.debug("Using Link Speed for Route Metrics");
-                for (NodePortTuple npt : allLinks.keySet()) {
-                    if (allLinks.get(npt) == null) continue;
-                    rawLinkSpeed = TopologyManager.statisticsService.getLinkSpeed(npt);
-                    for (Link link : allLinks.get(npt)) {
-                        if (link == null) continue;
-
-                        if((rawLinkSpeed / 10^6) / 8 > 1){
-                            linkSpeedMBps = (int)(rawLinkSpeed / 10^6) / 8;
-                            linkCost.put(link, (1/linkSpeedMBps)*1000);
-                        }
-                        else
-                            linkCost.put(link, MAX_LINK_WEIGHT);
+        case LINK_SPEED:
+            if(TopologyManager.collectStatistics == false){
+                TopologyManager.statisticsService.collectStatistics(true);
+                TopologyManager.collectStatistics = true;
+            }
+            log.debug("Using Link Speed for Route Metrics");
+            for (NodePortTuple npt : allLinks.keySet()) {
+                if (allLinks.get(npt) == null) continue;
+                rawLinkSpeed = TopologyManager.statisticsService.getLinkSpeed(npt);
+                for (Link link : allLinks.get(npt)) {
+                    if (link == null) continue;
+
+                    if((rawLinkSpeed / 10^6) / 8 > 1){
+                        linkSpeedMBps = (int)(rawLinkSpeed / 10^6) / 8;
+                        linkCost.put(link, (1/linkSpeedMBps)*1000);
                     }
+                    else
+                        linkCost.put(link, MAX_LINK_WEIGHT);
                 }
-                return linkCost;
+            }
+            return linkCost;
 
-            default:
-                if(TopologyManager.collectStatistics == true){
-                    TopologyManager.statisticsService.collectStatistics(false);
-                    TopologyManager.collectStatistics = false;
-                }
-                log.debug("Invalid Selection: Using Default Hop Count with Tunnel Bias for Metrics");
-                for (NodePortTuple npt : tunnelPorts) {
-                    if (allLinks.get(npt) == null) continue;
-                    for (Link link : allLinks.get(npt)) {
-                        if (link == null) continue;
-                        linkCost.put(link, tunnel_weight);
-                    }
+        default:
+            if(TopologyManager.collectStatistics == true){
+                TopologyManager.statisticsService.collectStatistics(false);
+                TopologyManager.collectStatistics = false;
+            }
+            log.debug("Invalid Selection: Using Default Hop Count with Tunnel Bias for Metrics");
+            for (NodePortTuple npt : tunnelPorts) {
+                if (allLinks.get(npt) == null) continue;
+                for (Link link : allLinks.get(npt)) {
+                    if (link == null) continue;
+                    linkCost.put(link, tunnel_weight);
                 }
-                return linkCost;
+            }
+            return linkCost;
         }
     }
-	
+
     /*
-	 * Modification of the calculateShortestPathTreeInClusters (dealing with whole topology, not individual clusters)
-	 */
+     * Modification of the calculateShortestPathTreeInClusters (dealing with whole topology, not individual clusters)
+     */
     private void calculateAllShortestPaths() {
-    	this.broadcastNodePorts.clear();
-    	this.destinationRootedFullTrees.clear();
-    	Map<Link, Integer> linkCost = new HashMap<Link, Integer>();
+        this.broadcastNodePorts.clear();
+        this.destinationRootedFullTrees.clear();
+        Map<Link, Integer> linkCost = new HashMap<Link, Integer>();
         int tunnel_weight = switchPorts.size() + 1;
-		
+
         for (NodePortTuple npt : tunnelPorts) {
             if (allLinks.get(npt) == null) continue;
             for (Link link : allLinks.get(npt)) {
@@ -853,7 +846,7 @@ public class TopologyInstance {
                 linkCost.put(link, tunnel_weight);
             }
         }
-        
+
         Map<DatapathId, Set<Link>> linkDpidMap = new HashMap<DatapathId, Set<Link>>();
         for (DatapathId s : switches) {
             if (switchPorts.get(s) == null) continue;
@@ -861,18 +854,18 @@ public class TopologyInstance {
                 NodePortTuple np = new NodePortTuple(s, p);
                 if (allLinks.get(np) == null) continue;
                 for (Link l : allLinks.get(np)) {
-                	if (linkDpidMap.containsKey(s)) {
-                		linkDpidMap.get(s).add(l);
-                	}
-                	else {
-                		linkDpidMap.put(s, new HashSet<Link>(Arrays.asList(l)));
-                	}
+                    if (linkDpidMap.containsKey(s)) {
+                        linkDpidMap.get(s).add(l);
+                    }
+                    else {
+                        linkDpidMap.put(s, new HashSet<Link>(Arrays.asList(l)));
+                    }
                 }
             }
         }   
-        
+
         for (DatapathId node : linkDpidMap.keySet()) {
-        	BroadcastTree tree = dijkstra(linkDpidMap, node, linkCost, true);
+            BroadcastTree tree = dijkstra(linkDpidMap, node, linkCost, true);
             destinationRootedFullTrees.put(node, tree);
         }
     }
@@ -887,11 +880,21 @@ public class TopologyInstance {
         RouteId routeId;
         pathcache.clear();
 
-        for (DatapathId src : switches) {
-            for (DatapathId dst : switches) {
-                routes = yens(src, dst, TopologyManager.getMaxPathsToComputeInternal());
-                routeId = new RouteId(src, dst);
-                pathcache.put(routeId, routes);
+        for (Archipelago a : archipelagos) { /* for each archipelago */
+            Set<DatapathId> srcSws = a.getSwitches();
+            Set<DatapathId> dstSws = a.getSwitches();
+            log.info("SRC {}", srcSws);
+            log.info("DST {}", dstSws);
+
+            for (DatapathId src : srcSws) { /* permute all member switches */
+                for (DatapathId dst : dstSws) {
+                    log.warn("Calling Yens {} {}", src, dst);
+                    routes = yens(src, dst, TopologyManager.getMaxPathsToComputeInternal(),
+                            getArchipelago(src), getArchipelago(dst));
+                    routeId = new RouteId(src, dst);
+                    pathcache.put(routeId, routes);
+                    log.info("Adding paths {}", routes);
+                }
             }
         }
     }
@@ -945,25 +948,25 @@ public class TopologyInstance {
     }
 
     private void computeBcastPortsPerSwitchFromBcastNTPs(){
-		this.broadcastPortMap.clear();
-
-		for (DatapathId sw : this.switches) {
-			for (OFPort p : this.allPorts.get(sw)){
-				NodePortTuple npt = new NodePortTuple(sw, p);
-				if (isEdge(sw, p) || broadcastNodePorts.contains(npt)) { 
-					if (broadcastPortMap.containsKey(sw)) {
-                		broadcastPortMap.get(sw).add(p);
-                	} else {
-                		broadcastPortMap.put(sw, new HashSet<OFPort>(Arrays.asList(p)));
-                	}
-				}      		
-			}
-		}
+        this.broadcastPortMap.clear();
+
+        for (DatapathId sw : this.switches) {
+            for (OFPort p : this.allPorts.get(sw)){
+                NodePortTuple npt = new NodePortTuple(sw, p);
+                if (isEdge(sw, p) || broadcastNodePorts.contains(npt)) { 
+                    if (broadcastPortMap.containsKey(sw)) {
+                        broadcastPortMap.get(sw).add(p);
+                    } else {
+                        broadcastPortMap.put(sw, new HashSet<OFPort>(Arrays.asList(p)));
+                    }
+                }      		
+            }
+        }
     }
-	
+
     private void calculateBroadcastNodePortsInClusters() {
         clusterBroadcastTrees.clear();
-        
+
         calculateBroadcastTreeInClusters();
 
         for (Cluster c : clusters) {
@@ -995,9 +998,6 @@ public class TopologyInstance {
 
         if (tree == null) return new Route(id, ImmutableList.of()); /* empty route */
 
-        // TODO: Check if the src and dst are in the tree
-        // if (destinationRootedFullTrees.get(dstId) == null) return null;
-
         Map<DatapathId, Link> nexthoplinks = tree.getLinks();
 
         if (!switches.contains(srcId) || !switches.contains(dstId)) {
@@ -1009,7 +1009,7 @@ public class TopologyInstance {
             // The only possible non-null path for this case is
             // if srcId equals dstId --- and that too is an 'empty' path []
 
-        } else if ((nexthoplinks!=null) && (nexthoplinks.get(srcId) != null)) {
+        } else if ((nexthoplinks != null) && (nexthoplinks.get(srcId) != null)) {
             while (!srcId.equals(dstId)) {
                 Link l = nexthoplinks.get(srcId);
                 npt = new NodePortTuple(l.getSrc(), l.getSrcPort());
@@ -1112,12 +1112,21 @@ public class TopologyInstance {
         if (routes == null || k < 1) return ImmutableList.of();
 
         if (k >= TopologyManager.getMaxPathsToComputeInternal() || k >= routes.size()) {
-            return yens(src, dst, k); /* heavy computation */
+            return yens(src, dst, k, getArchipelago(src), getArchipelago(dst)); /* heavy computation */
         }
         else {
             return new ArrayList<Route>(routes.subList(0, k));
         }
     }
+    
+    private Archipelago getArchipelago(DatapathId d) {
+        for (Archipelago a : archipelagos) {
+            if (a.getSwitches().contains(d)) {
+                return a;
+            }
+        }
+        return null;
+    }
 
     protected void setPathCosts(Route r) {
         U64 cost = U64.ZERO;
@@ -1145,7 +1154,7 @@ public class TopologyInstance {
 
     }
 
-    private List<Route> yens(DatapathId src, DatapathId dst, Integer K) {
+    private List<Route> yens(DatapathId src, DatapathId dst, Integer K, Archipelago aSrc, Archipelago aDst) {
 
         log.debug("YENS ALGORITHM -----------------");
         log.debug("Asking for routes from {} to {}", src, dst);
@@ -1167,13 +1176,25 @@ public class TopologyInstance {
         if (K < 1) {
             return A;
         }
-
-        if (!switches.contains(src) || !switches.contains(dst)) {
+        
+        /* The switch is not a member of an archipelago. It must not be connected */
+        if (aSrc == null || aDst == null) {
+            log.warn("One or more switches not connected. Cannot compute path b/t {} and {}", src, dst);
+            return A;
+        }
+        
+        if (!aSrc.equals(aDst)) {
+            log.warn("Switches {} and {} not in same archipelago. Cannot compute path", src, dst);
             return A;
         }
 
-        // Use Dijkstra's to find the shortest path, which will also be the first path in A
-        Route newroute = buildPath(new RouteId(src, dst), dijkstra(copyOfLinkDpidMap, dst, linkCost, true));
+        /* Use Dijkstra's to find the shortest path, which will also be the first path in A */
+        BroadcastTree bt = dijkstra(copyOfLinkDpidMap, dst, linkCost, true);
+        /* add this initial tree as our archipelago's broadcast tree (aSrc == aDst) */
+        aSrc.setBroadcastTree(bt);
+        /* now add the shortest path */
+        log.warn("src {} dst {} tree {}", new Object[] {src, dst, bt});
+        Route newroute = buildPath(new RouteId(src, dst), bt); /* guaranteed to be in same tree */
 
         if (newroute != null && !newroute.getPath().isEmpty()) { /* should never be null, but might be empty */
             setPathCosts(newroute);
@@ -1340,16 +1361,16 @@ public class TopologyInstance {
         return shortestPath;
     }
 
-	/**
-	 * Computes end-to-end path including src/dst switch
-	 * ports in addition to the switches. This chains into
-	 * {@link #getPath(DatapathId, DatapathId)} below.
-	 * @param srcId
-	 * @param srcPort
-	 * @param dstId
-	 * @param dstPort
-	 * @return
-	 */
+    /**
+     * Computes end-to-end path including src/dst switch
+     * ports in addition to the switches. This chains into
+     * {@link #getPath(DatapathId, DatapathId)} below.
+     * @param srcId
+     * @param srcPort
+     * @param dstId
+     * @param dstPort
+     * @return
+     */
     protected Route getPath(DatapathId srcId, OFPort srcPort,
             DatapathId dstId, OFPort dstPort) {
         // Return null if the route source and destination are the
@@ -1362,7 +1383,7 @@ public class TopologyInstance {
         NodePortTuple npt;
         Route r = getPath(srcId, dstId);
         if (r == null && !srcId.equals(dstId)) {
-        	return null;
+            return null;
         }
 
         if (r != null) {
@@ -1379,7 +1400,7 @@ public class TopologyInstance {
         r = new Route(id, nptList);
         return r;
     }
-    
+
 
     /**
      * Get the fastest path from the pathcache.
@@ -1387,7 +1408,7 @@ public class TopologyInstance {
      * @param dstId
      * @return
      */
-    
+
     protected Route getPath(DatapathId srcId, DatapathId dstId) {
         // Return null route if srcId equals dstId
         if (srcId.equals(dstId)) return null;
@@ -1464,8 +1485,8 @@ public class TopologyInstance {
     }
 
     /*
-	 * Takes finiteBroadcastTree into account to prevent loops in the network
-	 */
+     * Takes finiteBroadcastTree into account to prevent loops in the network
+     */
     protected boolean isIncomingBroadcastAllowedOnSwitchPort(DatapathId sw, OFPort portId) {
         if (!isEdge(sw, portId)){       
             NodePortTuple npt = new NodePortTuple(sw, portId);
diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
index 4117ad3a7e80e5d373f9a169d9d5ff5faa5c9d47..bd963058f3aa9ef16a9c66f587147e21c328e81e 100644
--- a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
+++ b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
@@ -676,18 +676,19 @@ public class TopologyInstanceTest {
          */
         int [][] linkArray = {
                 {1, 1, 2, 1, DIRECT_LINK},
+                //{3, 1, 1, 2, DIRECT_LINK},
                 {1, 2, 3, 1, DIRECT_LINK},
                 {2, 2, 3, 2, DIRECT_LINK},
         };
-        int [] lat = {1,50,1};
+        int [] lat = {1,/*50,*/50,1};
 
         /* 
          * NOTE: Output from the next four log.info should be mirrored!
          * Get paths based on latency.
          */
+        topologyManager.clearCurrentTopology();
         topologyManager.setPathMetric(LATENCY);
         configureTopology(linkArray, lat);
-        topologyManager.createNewInstance();
         List<Route> lat_paths = topologyManager.getPathsFast(one, three, k);
         log.info("Path 1: {}", lat_paths.get(0));
         log.info("Path 2: {}", lat_paths.get(1));