diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
index a2af40ba7745c1f48de3656ff4199409a2f6c5ab..856ec0bda2267604688621387742e211d090793d 100644
--- a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
+++ b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
@@ -173,4 +173,20 @@ public interface IRoutingService extends IFloodlightService {
      * @return list of paths ordered least to greatest cost
      */
     public List<Path> getPathsSlow(DatapathId src, DatapathId dst, int numReqPaths);
+    
+    /**
+     * Recompute paths now, regardless of whether or not there was a change in the
+     * topology. This should be called if {@link #setPathMetric(PATH_METRIC)} was
+     * invoked to change the PATH_METRIC **and we want the new metric to take effect
+     * now** for future getPathsFast() or getPath() function calls. This will allow other 
+     * modules using IRoutingService path-finding to use paths based on the new metric
+     * if the other modules only use the "fast" path-finding API. 
+     * 
+     * One can use {@link IRoutingService#getPathsSlow(DatapathId, DatapathId, int)} if there is no
+     * urgency for the new metric to take effect and yet one would still like to see 
+     * the paths using the new metric once or so. In this case, one need not invoke {@link #forceRecompute()}.
+     * 
+     * @return true upon success; false otherwise
+     */
+    public boolean forceRecompute();
 }
diff --git a/src/main/java/net/floodlightcontroller/routing/RoutingManager.java b/src/main/java/net/floodlightcontroller/routing/RoutingManager.java
index 8268cee5395794637ac79b61d52d63913bac88d4..3110da7470d76371afd37d53c9350ac3def3b36f 100644
--- a/src/main/java/net/floodlightcontroller/routing/RoutingManager.java
+++ b/src/main/java/net/floodlightcontroller/routing/RoutingManager.java
@@ -122,6 +122,11 @@ public class RoutingManager implements IFloodlightModule, IRoutingService {
     public boolean pathExists(DatapathId src, DatapathId dst) {
         return tm.getCurrentTopologyInstance().pathExists(src, dst);
     }
+    
+    @Override
+    public boolean forceRecompute() {
+        return tm.forceRecompute();
+    }
 
     /** 
      * Registers an IRoutingDecisionChangedListener.
@@ -157,5 +162,4 @@ public class RoutingManager implements IFloodlightModule, IRoutingService {
             listener.routingDecisionChanged(changedDecisions);
         }
     }
-
 }
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/routing/web/ForceRecomputeResource.java b/src/main/java/net/floodlightcontroller/routing/web/ForceRecomputeResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce408644d53a60fb29ee78b2f63f126ffe103089
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/routing/web/ForceRecomputeResource.java
@@ -0,0 +1,44 @@
+/**
+ *    Copyright 2013, Big Switch Networks, Inc.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
+package net.floodlightcontroller.routing.web;
+
+import net.floodlightcontroller.routing.IRoutingService;
+import org.restlet.resource.Post;
+import org.restlet.resource.Put;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+
+public class ForceRecomputeResource extends ServerResource {
+    private static final Logger log = LoggerFactory.getLogger(ForceRecomputeResource.class);
+
+    @Put
+    @Post
+    public Map<String, String> forceRecompute() {
+        IRoutingService routing =
+                (IRoutingService)getContext().getAttributes().
+                        get(IRoutingService.class.getCanonicalName());
+
+        boolean result = routing.forceRecompute();
+        log.debug("Force recompute result {}", result);
+        return ImmutableMap.of("result", result ? "paths recomputed" : "error recomputing paths");
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/routing/web/MaxFastPathsResource.java b/src/main/java/net/floodlightcontroller/routing/web/MaxFastPathsResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c0b193425827314a3652110388cf36f4f9ffd92
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/routing/web/MaxFastPathsResource.java
@@ -0,0 +1,109 @@
+/**
+ *    Copyright 2013, Big Switch Networks, Inc.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
+package net.floodlightcontroller.routing.web;
+
+import net.floodlightcontroller.routing.IRoutingService;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.Post;
+import org.restlet.resource.Put;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.MappingJsonFactory;
+import com.google.common.collect.ImmutableMap;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+public class MaxFastPathsResource extends ServerResource {
+    private static final Logger log = LoggerFactory.getLogger(MaxFastPathsResource.class);
+
+    private static String maxPathsFromJson(String json) {
+        MappingJsonFactory f = new MappingJsonFactory();
+        JsonParser jp;
+        String max = "";
+        try {
+            try {
+                jp = f.createParser(json);
+            } catch (JsonParseException e) {
+                throw new IOException(e);
+            }
+
+            jp.nextToken();
+            if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
+                throw new IOException("Expected START_OBJECT");
+            }
+
+            while (jp.nextToken() != JsonToken.END_OBJECT) {
+                if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
+                    throw new IOException("Expected FIELD_NAME");
+                }
+
+                String n = jp.getCurrentName();
+                jp.nextToken();
+                if (jp.getText().equals("")) {
+                    continue;
+                }
+
+                if (n.equalsIgnoreCase("max_fast_paths")) {
+                    max = jp.getText();
+                }
+            }
+        } catch (IOException e) {
+            log.error("Unable to parse JSON string: {}", e);
+        }
+        return max.trim().toLowerCase();
+    }
+
+    @Put
+    @Post
+    public Map<String, String> changeMaxPathsToCompute(String json) {
+        IRoutingService routing =
+                (IRoutingService)getContext().getAttributes().
+                get(IRoutingService.class.getCanonicalName());
+
+        int max = 0;
+        
+        try {
+            max = Integer.parseInt(maxPathsFromJson(json));
+            if (max < 0) {
+                throw new NumberFormatException();
+            }
+        } catch (NumberFormatException e) {
+            log.error("Could not parse max_fast_paths {}", max);
+            return Collections.singletonMap("error", "invalid max_fast_paths: " + max);
+        }
+
+        log.debug("Setting max_fast_paths to {}", max);
+        routing.setMaxPathsToCompute(max);
+        return ImmutableMap.of("max_fast_paths", Integer.toString(routing.getMaxPathsToCompute()));
+    }
+
+    @Get
+    public Map<String, String> getMaxPaths() {
+        IRoutingService routing =
+                (IRoutingService)getContext().getAttributes().
+                get(IRoutingService.class.getCanonicalName());
+        return ImmutableMap.of("max_fast_paths", Integer.toString(routing.getMaxPathsToCompute()));
+    }
+}
\ 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 cf032a135520f0395eefa7a405409f673af901d8..c9c51380abac5bdac6ada7545cdbea7fdd34bb6c 100644
--- a/src/main/java/net/floodlightcontroller/routing/web/PathMetricsResource.java
+++ b/src/main/java/net/floodlightcontroller/routing/web/PathMetricsResource.java
@@ -18,53 +18,101 @@ package net.floodlightcontroller.routing.web;
 
 import net.floodlightcontroller.routing.IRoutingService;
 import net.floodlightcontroller.routing.IRoutingService.PATH_METRIC;
+
+import org.restlet.resource.Get;
 import org.restlet.resource.Post;
 import org.restlet.resource.Put;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.MappingJsonFactory;
+import com.google.common.collect.ImmutableMap;
+
+import java.io.IOException;
 import java.util.Collections;
 import java.util.Map;
 
 public class PathMetricsResource extends ServerResource {
     private static final Logger log = LoggerFactory.getLogger(PathMetricsResource.class);
 
+    private static String metricFromJson(String json) {
+        MappingJsonFactory f = new MappingJsonFactory();
+        JsonParser jp;
+        String metric = "";
+        try {
+            try {
+                jp = f.createParser(json);
+            } catch (JsonParseException e) {
+                throw new IOException(e);
+            }
+
+            jp.nextToken();
+            if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
+                throw new IOException("Expected START_OBJECT");
+            }
+
+            while (jp.nextToken() != JsonToken.END_OBJECT) {
+                if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
+                    throw new IOException("Expected FIELD_NAME");
+                }
+
+                String n = jp.getCurrentName();
+                jp.nextToken();
+                if (jp.getText().equals("")) {
+                    continue;
+                }
+
+                if (n.equalsIgnoreCase("metric")) {
+                    metric = jp.getText();
+                }
+            }
+        } catch (IOException e) {
+            log.error("Unable to parse JSON string: {}", e);
+        }
+        return metric.trim().toLowerCase();
+    }
+
     @Put
     @Post
-    public Map<String, String> changeMetric() {
+    public Map<String, String> changeMetric(String json) {
         IRoutingService routing =
                 (IRoutingService)getContext().getAttributes().
-                        get(IRoutingService.class.getCanonicalName());
+                get(IRoutingService.class.getCanonicalName());
 
-        String metric = (String) getRequestAttributes().get("metric");
-        metric = metric.trim().toLowerCase();
+        String metric = metricFromJson(json);
 
         PATH_METRIC type;
 
-        switch (metric) {
-            case "latency":
-                type = PATH_METRIC.LATENCY;
-                break;
-            case "utilization":
-                type = PATH_METRIC.UTILIZATION;
-                break;
-            case "hopcount":
-                type = PATH_METRIC.HOPCOUNT;
-                break;
-            case "hopcount_avoid_tunnels":
-                type = PATH_METRIC.HOPCOUNT_AVOID_TUNNELS;
-                break;
-            case "link_speed":
-                type = PATH_METRIC.LINK_SPEED;
-                break;
-            default:
-                log.error("Invalid input {}", metric);
-                return Collections.singletonMap("error", "invalid path metric " + metric);
+        if (metric.equals(PATH_METRIC.LATENCY.getMetricName())) {
+            type = PATH_METRIC.LATENCY;
+        } else if (metric.equals(PATH_METRIC.UTILIZATION.getMetricName())) {
+            type = PATH_METRIC.UTILIZATION;
+        } else if (metric.equals(PATH_METRIC.HOPCOUNT.getMetricName())) {
+            type = PATH_METRIC.HOPCOUNT;
+        } else if (metric.equals(PATH_METRIC.HOPCOUNT_AVOID_TUNNELS.getMetricName())) {
+            type = PATH_METRIC.HOPCOUNT_AVOID_TUNNELS;
+        } else if (metric.equals(PATH_METRIC.LINK_SPEED.getMetricName())) {
+            type = PATH_METRIC.LINK_SPEED;
+        } else {
+            log.error("Invalid input {}", metric);
+            return Collections.singletonMap("error", "invalid path metric: " + metric);
         }
 
         log.debug("Setting path metric to {}", type.getMetricName());
         routing.setPathMetric(type);
-        return Collections.singletonMap("success", "path metric set to " + type.getMetricName());
+        return Collections.singletonMap("metric", type.getMetricName());
+    }
+
+    @Get
+    public Map<String, String> getMetric() {
+        IRoutingService routing =
+                (IRoutingService)getContext().getAttributes().
+                get(IRoutingService.class.getCanonicalName());
+        PATH_METRIC metric = routing.getPathMetric();
+        return ImmutableMap.of("metric", metric.getMetricName());
     }
 }
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/routing/web/RoutingWebRoutable.java b/src/main/java/net/floodlightcontroller/routing/web/RoutingWebRoutable.java
index d9901f0fbb82a133030703847bddb88d60708345..b56a2a5b6f5f407b056284e997e89b8fad5b300e 100644
--- a/src/main/java/net/floodlightcontroller/routing/web/RoutingWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/routing/web/RoutingWebRoutable.java
@@ -35,8 +35,9 @@ public class RoutingWebRoutable implements RestletRoutable {
         router.attach("/paths/{src-dpid}/{dst-dpid}/{num-paths}/json", PathsResource.class);
         router.attach("/paths/fast/{src-dpid}/{dst-dpid}/{num-paths}/json", PathsResource.class);
         router.attach("/paths/slow/{src-dpid}/{dst-dpid}/{num-paths}/json", PathsResource.class);
-        router.attach("/setpathmetric/{metric}/json", PathMetricsResource.class);
-
+        router.attach("/metric/json", PathMetricsResource.class);
+        router.attach("/paths/force-recompute/json", ForceRecomputeResource.class);
+        router.attach("/paths/max-fast-paths/json", MaxFastPathsResource.class);
         return router;
     }
 
diff --git a/src/main/java/net/floodlightcontroller/statistics/IStatisticsService.java b/src/main/java/net/floodlightcontroller/statistics/IStatisticsService.java
index 7cc047233312e8ca492b1556403ac7a811bd527f..9075d98d291a9a91776a7b5a84dbc965b0f09c12 100644
--- a/src/main/java/net/floodlightcontroller/statistics/IStatisticsService.java
+++ b/src/main/java/net/floodlightcontroller/statistics/IStatisticsService.java
@@ -12,8 +12,6 @@ public interface IStatisticsService extends IFloodlightService {
 	public SwitchPortBandwidth getBandwidthConsumption(DatapathId dpid, OFPort p);
 		
 	public Map<NodePortTuple, SwitchPortBandwidth> getBandwidthConsumption();
-
-	public long getLinkSpeed(NodePortTuple npt);
 	
 	public void collectStatistics(boolean collect);
 }
diff --git a/src/main/java/net/floodlightcontroller/statistics/StatisticsCollector.java b/src/main/java/net/floodlightcontroller/statistics/StatisticsCollector.java
index 50f441bd52b3a61a6ad6c3fcb06361cd8f6ce7df..97bd54aef17338adefe770c0ae3dc16b5f0e8b13 100644
--- a/src/main/java/net/floodlightcontroller/statistics/StatisticsCollector.java
+++ b/src/main/java/net/floodlightcontroller/statistics/StatisticsCollector.java
@@ -242,10 +242,6 @@ public class StatisticsCollector implements IFloodlightModule, IStatisticsServic
 		return Collections.unmodifiableMap(portStats);
 	}
 
-	public long getLinkSpeed(NodePortTuple npt) {
-		return portStats.get(npt).getLinkSpeedBitsPerSec().getValue();
-	}
-
 	@Override
 	public synchronized void collectStatistics(boolean collect) {
 		if (collect && !isEnabled) {
diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyManagerBackend.java b/src/main/java/net/floodlightcontroller/topology/ITopologyManagerBackend.java
index 64c4e06a2abcf3581fa23e5a99a96503d92d727d..542a7728e4b42c2291ab8d8d36cce1b7abe69270 100644
--- a/src/main/java/net/floodlightcontroller/topology/ITopologyManagerBackend.java
+++ b/src/main/java/net/floodlightcontroller/topology/ITopologyManagerBackend.java
@@ -2,7 +2,7 @@ package net.floodlightcontroller.topology;
 
 import net.floodlightcontroller.routing.IRoutingService.PATH_METRIC;
 
-public interface ITopologyManagerBackend {
+public interface ITopologyManagerBackend extends ITopologyService {
     public TopologyInstance getCurrentTopologyInstance();
     
     public PATH_METRIC getPathMetric();
@@ -10,4 +10,6 @@ public interface ITopologyManagerBackend {
     
     public int getMaxPathsToCompute();
     public void setMaxPathsToCompute(int max);
+    
+    public boolean forceRecompute();
 }
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyPathFinding.java b/src/main/java/net/floodlightcontroller/topology/ITopologyPathFinding.java
new file mode 100644
index 0000000000000000000000000000000000000000..3260f460650910f2331a6a1ff0095fc15e23efc4
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/topology/ITopologyPathFinding.java
@@ -0,0 +1,7 @@
+package net.floodlightcontroller.topology;
+
+import net.floodlightcontroller.routing.IRoutingService;
+
+public interface ITopologyPathFinding extends IRoutingService {
+
+}
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
index fbd6bf8a4208cfa2a554f59cd66fcc2d3341a0c1..80a41d494740494e665c69d651e4dd3eda4340e0 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
@@ -16,12 +16,16 @@
 
 package net.floodlightcontroller.topology;
 
+import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.types.NodePortTuple;
 import net.floodlightcontroller.linkdiscovery.Link;
 import net.floodlightcontroller.routing.BroadcastTree;
 import net.floodlightcontroller.routing.Path;
 import net.floodlightcontroller.routing.PathId;
+import net.floodlightcontroller.statistics.SwitchPortBandwidth;
 import net.floodlightcontroller.util.ClusterDFS;
+
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.U64;
@@ -643,92 +647,113 @@ public class TopologyInstance {
      */
     public Map<Link,Integer> initLinkCostMap() {
         Map<Link, Integer> linkCost = new HashMap<Link, Integer>();
-        long rawLinkSpeed;
-        int linkSpeedMBps;
         int tunnel_weight = portsWithLinks.size() + 1;
 
-        /* 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");
+            log.debug("Using hop count with tunnel bias for metrics");
             for (NodePortTuple npt : portsTunnel) {
-                if (links.get(npt) == null) continue;
+                if (links.get(npt) == null) {
+                    continue;
+                }
                 for (Link link : links.get(npt)) {
-                    if (link == null) continue;
+                    if (link == null) {
+                        continue;
+                    }
                     linkCost.put(link, tunnel_weight);
                 }
             }
             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");
+            log.debug("Using hop count w/o tunnel bias for metrics");
             for (NodePortTuple npt : links.keySet()) {
-                if (links.get(npt) == null) continue;
+                if (links.get(npt) == null) {
+                    continue;
+                }
                 for (Link link : links.get(npt)) {
-                    if (link == null) continue;
+                    if (link == null) {
+                        continue;
+                    }
                     linkCost.put(link,1);
                 }
             }
             return linkCost;
 
         case LATENCY:
-            if(TopologyManager.collectStatistics == true){
-                TopologyManager.statisticsService.collectStatistics(false);
-                TopologyManager.collectStatistics = false;
-            }
-            log.debug("Using Latency for Route Metrics");
+            log.debug("Using latency for path metrics");
             for (NodePortTuple npt : links.keySet()) {
-                if (links.get(npt) == null) continue;
+                if (links.get(npt) == null) {
+                    continue;
+                }
                 for (Link link : links.get(npt)) {
-                    if (link == null) continue;
-                    if((int)link.getLatency().getValue() < 0 || (int)link.getLatency().getValue() > MAX_LINK_WEIGHT)
+                    if (link == null) {
+                        continue;
+                    }
+                    if ((int)link.getLatency().getValue() < 0 || 
+                            (int)link.getLatency().getValue() > MAX_LINK_WEIGHT) {
                         linkCost.put(link, MAX_LINK_WEIGHT);
-                    else
+                    } else {
                         linkCost.put(link,(int)link.getLatency().getValue());
+                    }
                 }
             }
             return linkCost;
 
         case LINK_SPEED:
-            if(TopologyManager.collectStatistics == false){
-                TopologyManager.statisticsService.collectStatistics(true);
-                TopologyManager.collectStatistics = true;
-            }
-            log.debug("Using Link Speed for Route Metrics");
+            TopologyManager.statisticsService.collectStatistics(true);
+            log.debug("Using link speed for path metrics");
             for (NodePortTuple npt : links.keySet()) {
-                if (links.get(npt) == null) continue;
-                rawLinkSpeed = TopologyManager.statisticsService.getLinkSpeed(npt);
+                if (links.get(npt) == null) {
+                    continue;
+                }
+                long rawLinkSpeed = 0;
+                IOFSwitch s = TopologyManager.switchService.getSwitch(npt.getNodeId());
+                if (s != null) {
+                    OFPortDesc p = s.getPort(npt.getPortId());
+                    if (p != null) {
+                        rawLinkSpeed = p.getCurrSpeed();
+                    }
+                }
                 for (Link link : links.get(npt)) {
-                    if (link == null) continue;
+                    if (link == null) {
+                        continue;
+                    }
 
-                    if((rawLinkSpeed / 10^6) / 8 > 1){
-                        linkSpeedMBps = (int)(rawLinkSpeed / 10^6) / 8;
+                    if ((rawLinkSpeed / 10^6) / 8 > 1) {
+                        int linkSpeedMBps = (int)(rawLinkSpeed / 10^6) / 8;
                         linkCost.put(link, (1/linkSpeedMBps)*1000);
+                    } else {
+                        linkCost.put(link, MAX_LINK_WEIGHT);
                     }
-                    else
+                }
+            }
+            return linkCost;
+            
+        case UTILIZATION:
+            TopologyManager.statisticsService.collectStatistics(true);
+            log.debug("Using utilization for path metrics");
+            for (NodePortTuple npt : links.keySet()) {
+                if (links.get(npt) == null) continue;
+                SwitchPortBandwidth spb = TopologyManager.statisticsService
+                        .getBandwidthConsumption(npt.getNodeId(), npt.getPortId());
+                long bpsTx = spb.getBitsPerSecondTx().getValue();
+                for (Link link : links.get(npt)) {
+                    if (link == null) {
+                        continue;
+                    }
+
+                    if ((bpsTx / 10^6) / 8 > 1) {
+                        int cost = (int) (bpsTx / 10^6) / 8;
+                        linkCost.put(link, ((1/cost)*1000));
+                    } else {
                         linkCost.put(link, MAX_LINK_WEIGHT);
+                    }
                 }
             }
             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 : portsTunnel) {
                 if (links.get(npt) == null) continue;
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index ffeb928fda25e0826ee39b0ee0576026734901fe..77dcc9651f6fc08c3b7bd76af854be4b19fee9b5 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -62,16 +62,12 @@ import java.util.concurrent.TimeUnit;
  * through the topology.
  */
 public class TopologyManager implements IFloodlightModule, ITopologyService, 
-    ITopologyManagerBackend, ILinkDiscoveryListener, IOFMessageListener {
-
-    protected static Logger log = LoggerFactory.getLogger(TopologyManager.class);
+ITopologyManagerBackend, ILinkDiscoveryListener, IOFMessageListener {
+    private 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.
      */
@@ -107,12 +103,13 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
      */
     protected Set<NodePortTuple> tunnelPorts;
 
-    protected ILinkDiscoveryService linkDiscoveryService;
-    protected IThreadPoolService threadPoolService;
-    protected IFloodlightProviderService floodlightProviderService;
-    protected IOFSwitchService switchService;
-    protected IRestApiService restApiService;
-    protected IDebugCounterService debugCounterService;
+    protected static ILinkDiscoveryService linkDiscoveryService;
+    protected static IThreadPoolService threadPoolService;
+    protected static IFloodlightProviderService floodlightProviderService;
+    protected static IOFSwitchService switchService;
+    protected static IRestApiService restApiService;
+    protected static IDebugCounterService debugCounterService;
+    protected static IStatisticsService statisticsService;
 
     // Modules that listen to our updates
     protected ArrayList<ITopologyListener> topologyAware;
@@ -177,8 +174,8 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
         @Override
         public void run() {
             try {
-                if (ldUpdates.peek() != null) {
-                    updateTopology();
+                if (ldUpdates.peek() != null) { /* must check here, otherwise will run every interval */
+                    updateTopology("link-discovery-updates", false);
                 }
                 handleMiscellaneousPeriodicEvents();
             }
@@ -197,13 +194,17 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
         return;
     }
 
-    public boolean updateTopology() {
+    public synchronized boolean updateTopology(String reason, boolean forced) {
         boolean newInstanceFlag;
         linksUpdated = false;
         dtLinksUpdated = false;
         tunnelPortsUpdated = false;
-        List<LDUpdate> appliedUpdates = applyUpdates();
-        newInstanceFlag = createNewInstance("link-discovery-updates");
+        List<LDUpdate> appliedUpdates = null;
+        if (this.ldUpdates.peek() != null) {
+            appliedUpdates = applyUpdates();
+        }
+        log.info("Recomputing topology due to: {}", reason);
+        newInstanceFlag = createNewInstance(reason, forced);
         lastUpdateTime = new Date();
         informListeners(appliedUpdates);
         return newInstanceFlag;
@@ -621,22 +622,23 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
                         pathMetric = PATH_METRIC.LINK_SPEED;
                         break;
                     default:
-                        log.error("Invalid routing metric {}. Using default {}", metric, pathMetric.getMetricName());
+                        log.error("Invalid routing metric {}. Using default {}", 
+                                metric, pathMetric.getMetricName());
                         break;
                     }
                 }
                 log.info("Path metrics set to {}", pathMetric);
 
-                String maxroutes = configOptions.get("maxPathsToCompute") != null
+                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);
+                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
@@ -932,7 +934,7 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
     }
 
     public boolean createNewInstance() {
-        return createNewInstance("internal");
+        return createNewInstance("internal", false);
     }
 
     /**
@@ -941,10 +943,12 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
      * and tunnel ports. The method returns if a new instance of
      * topology was created or not.
      */
-    protected boolean createNewInstance(String reason) {
+    protected boolean createNewInstance(String reason, boolean forced) {
         Set<NodePortTuple> blockedPorts = new HashSet<NodePortTuple>();
 
-        if (!linksUpdated) return false;
+        if (!linksUpdated && !forced) {
+            return false;
+        }
 
         Map<NodePortTuple, Set<Link>> openflowLinks;
         openflowLinks =
@@ -1064,9 +1068,12 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
 
 
     public void informListeners(List<LDUpdate> linkUpdates) {
-
-        if (role != null && role != HARole.ACTIVE)
+        if (linkUpdates == null || linkUpdates.isEmpty()) {
+            return;
+        }
+        if (role != null && role != HARole.ACTIVE) {
             return;
+        }
 
         for(int i=0; i < topologyAware.size(); ++i) {
             ITopologyListener listener = topologyAware.get(i);
@@ -1248,7 +1255,7 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
         linksUpdated = true;
         dtLinksUpdated = true;
         tunnelPortsUpdated = true;
-        createNewInstance("startup");
+        createNewInstance("startup", false);
         lastUpdateTime = new Date();
     }
 
@@ -1320,4 +1327,10 @@ public class TopologyManager implements IFloodlightModule, ITopologyService,
     public TopologyInstance getCurrentTopologyInstance() {
         return getCurrentInstance();
     }
+
+    @Override
+    public boolean forceRecompute() {
+        /* cannot invoke scheduled executor, since the update might not occur */
+        return updateTopology("forced-recomputation", true);
+    }
 }
\ No newline at end of file