diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
index 67345322dfeb7f1e4d3707cb007562ea4d36a47c..74fbcdd136456e64647afe6a61b52610bde789eb 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
@@ -110,7 +110,7 @@ public interface IOFSwitch {
      * been received.
      * @return Unmodifiable list of ports
      */
-    public List<OFPhysicalPort> getEnabledPorts();
+    public List<Short> getEnabledPorts();
 
     /**
      * Retrieve the port object by the port number. The port object
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
index 3f42059d91da2af5a2140b72481b2d2d3eb2ae24..4a6fd51a72893a20be353990cea914fbb6358b49 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
@@ -257,11 +257,11 @@ public class OFSwitchImpl implements IOFSwitch {
     }
 
     @JsonIgnore
-    public synchronized List<OFPhysicalPort> getEnabledPorts() {
-        List<OFPhysicalPort> result = new ArrayList<OFPhysicalPort>();
+    public synchronized List<Short> getEnabledPorts() {
+        List<Short> result = new ArrayList<Short>();
         for (OFPhysicalPort port : ports.values()) {
             if (portEnabled(port)) {
-                result.add(port);
+                result.add(port.getPortNumber());
             }
         }
         return result;
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
index c4421acfcf4971431da1efa0f5686df4871cf54f..894f9f60440d4d32ff30cfb43c900096ac155148 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
@@ -65,4 +65,9 @@ public interface ILinkDiscoveryService extends IFloodlightService {
      * Removes a switch port from suppress lldp set
      */
     public void RemoveFromSuppressLLDPs(long sw, short port);
+
+    /**
+     * Get the set of quarantined ports on a switch
+     */
+    public Set<Short> getQuarantinedPorts(long sw);
 }
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
index ce205b17fdbf04b5648b0f4c8ccd25077c907654..c35be96b2824ab73780ab51772a83f19da193125 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
@@ -130,7 +130,6 @@ IFloodlightModule, IInfoProvider, IHAListener {
     private static final String LINK_DST_PORT_STATE = "dst_port_state";
     private static final String LINK_VALID_TIME = "valid_time";
     private static final String LINK_TYPE = "link_type";
-
     private static final String SWITCH_CONFIG_TABLE_NAME = "controller_switchconfig";
     private static final String SWITCH_CONFIG_CORE_SWITCH = "core_switch";
 
@@ -139,6 +138,7 @@ IFloodlightModule, IInfoProvider, IHAListener {
     protected IThreadPoolService threadPool;
 
 
+    // LLDP and BDDP fields
     private static final byte[] LLDP_STANDARD_DST_MAC_STRING = 
             HexString.fromHexString("01:80:c2:00:00:0e");
     private static final long LINK_LOCAL_MASK  = 0xfffffffffff0L;
@@ -167,12 +167,12 @@ IFloodlightModule, IInfoProvider, IHAListener {
     setLength((short)TLV_DIRECTION_LENGTH).
     setValue(TLV_DIRECTION_VALUE_REVERSE);
 
+    // Link discovery task details.
     protected SingletonTask discoveryTask;
     protected final int DISCOVERY_TASK_INTERVAL = 1; 
     protected final int LINK_TIMEOUT = 35; // timeout as part of LLDP process.
     protected final int LLDP_TO_ALL_INTERVAL = 15 ; //15 seconds.
     protected long lldpClock = 0;
-
     // This value is intentionally kept higher than LLDP_TO_ALL_INTERVAL.
     // If we want to identify link failures faster, we could decrease this
     // value to a small number, say 1 or 2 sec.
@@ -196,7 +196,6 @@ IFloodlightModule, IInfoProvider, IHAListener {
      * Map from a id:port to the set of links containing it as an endpoint
      */
     protected Map<NodePortTuple, Set<Link>> portLinks;
-    protected Set<NodePortTuple> suppressLLDPs;
 
     /**
      * Set of link tuples over which multicast LLDPs are received
@@ -212,6 +211,30 @@ IFloodlightModule, IInfoProvider, IHAListener {
     protected BlockingQueue<LDUpdate> updates;
     protected Thread updatesThread;
 
+    /**
+     * List of ports through which LLDP/BDDPs are not sent.
+     */
+    protected Set<NodePortTuple> suppressLLDPs;
+
+    /** A list of ports that are quarantined for discovering links through
+     * them.  Data traffic from these ports are not allowed until the ports
+     * are released from quarantine.
+     */
+    protected LinkedBlockingQueue<NodePortTuple> quarantineQueue;
+    protected LinkedBlockingQueue<NodePortTuple> maintenanceQueue;
+    /**
+     * Quarantine task
+     */
+    protected SingletonTask bddpTask;
+    protected final int BDDP_TASK_INTERVAL = 100; // 100 ms.
+    protected final int BDDP_TASK_SIZE = 5;       // # of ports per iteration
+
+    /**
+     * Map of broadcast domain ports and the last time a BDDP was either
+     * sent or received on that port.
+     */
+    protected Map<NodePortTuple, Long> broadcastDomainPortTimeMap;
+
     /** 
      * Get the LLDP sending period in seconds.
      * @return LLDP sending period in seconds.
@@ -262,6 +285,10 @@ IFloodlightModule, IInfoProvider, IHAListener {
         return shuttingDown;
     }
 
+    public boolean isFastPort(long sw, short port) {
+        return false;
+    }
+
     public ILinkDiscovery.LinkType getLinkType(Link lt, LinkInfo info) {
         if (info.getUnicastValidTime() != null) {
             return ILinkDiscovery.LinkType.DIRECT_LINK;
@@ -294,7 +321,6 @@ IFloodlightModule, IInfoProvider, IHAListener {
             }
         } while (updates.peek() != null);
     }
-
     private boolean isLLDPSuppressed(long sw, short portNumber) {
         return this.suppressLLDPs.contains(new NodePortTuple(sw, portNumber));
     }
@@ -313,8 +339,133 @@ IFloodlightModule, IInfoProvider, IHAListener {
         }
     }
 
+
+    /**
+     *  Quarantine Ports.
+     */
+    protected class QuarantineWorker implements Runnable {
+        @Override
+        public void run() {
+            try {
+                processBDDPLists();
+            }
+            catch (Exception e) {
+                log.error("Error in quarantine worker thread", e);
+            } finally {
+                    bddpTask.reschedule(BDDP_TASK_INTERVAL,
+                                              TimeUnit.MILLISECONDS);
+            }
+        }
+    }
+
+    /**
+     * Add a switch port to the quarantine queue. Schedule the
+     * quarantine task if the quarantine queue was empty before adding
+     * this switch port.
+     * @param npt
+     */
+    protected void addToQuarantineQueue(NodePortTuple npt) {
+        if (quarantineQueue.contains(npt) == false)
+            quarantineQueue.add(npt);
+    }
+
+    /**
+     * Remove a switch port from the quarantine queue.
+     */
+    protected void removeFromQuarantineQueue(NodePortTuple npt) {
+        // Remove all occurrences of the node port tuple from the list.
+        while (quarantineQueue.remove(npt));
+    }
+
+    /**
+     * Add a switch port to maintenance queue.
+     * @param npt
+     */
+    protected void addToMaintenanceQueue(NodePortTuple npt) {
+        // TODO We are not checking if the switch port tuple is already
+        // in the maintenance list or not.  This will be an issue for
+        // really large number of switch ports in the network.
+        maintenanceQueue.add(npt);
+    }
+
+    /**
+     * Remove a switch port from maintenance queue.
+     * @param npt
+     */
+    protected void removeFromMaintenanceQueue(NodePortTuple npt) {
+        // Remove all occurrences of the node port tuple from the queue.
+        while (maintenanceQueue.remove(npt));
+    }
+
+    /**
+    * This method processes the quarantine list in bursts.  The task is
+    * at most once per BDDP_TASK_INTERVAL.
+    * One each call, BDDP_TASK_SIZE number of switch ports are processed.
+    * Once the BDDP packets are sent out through the switch ports, the ports
+    * are removed from the quarantine list.
+    */
+
+    protected void processBDDPLists() {
+        int count = 0;
+        Set<NodePortTuple> nptList = new HashSet<NodePortTuple>();
+
+        while(count < BDDP_TASK_SIZE && quarantineQueue.peek() !=null) {
+            NodePortTuple npt;
+            npt = quarantineQueue.remove();
+            sendDiscoveryMessage(npt.getNodeId(), npt.getPortId(), false, false);
+            nptList.add(npt);
+            count++;
+        }
+
+        count = 0;
+        while (count < BDDP_TASK_SIZE && maintenanceQueue.peek() != null) {
+            NodePortTuple npt;
+            npt = maintenanceQueue.remove();
+            sendDiscoveryMessage(npt.getNodeId(), npt.getPortId(), false, false);
+            nptList.add(npt);
+            count++;
+        }
+
+        for(NodePortTuple npt:nptList) {
+            generateSwitchPortStatusUpdate(npt.getNodeId(), npt.getPortId());
+        }
+    }
+
+    public Set<Short> getQuarantinedPorts(long sw) {
+        Set<Short> qPorts = new HashSet<Short>();
+
+        Iterator<NodePortTuple> iter = quarantineQueue.iterator();
+        while (iter.hasNext()) {
+            NodePortTuple npt = iter.next();
+            if (npt.getNodeId() == sw) {
+                qPorts.add(npt.getPortId());
+            }
+        }
+        return qPorts;
+    }
+
+    private void generateSwitchPortStatusUpdate(long sw, short port) {
+        UpdateOperation operation;
+
+        IOFSwitch iofSwitch = floodlightProvider.getSwitches().get(sw);
+        if (iofSwitch == null) return;
+
+        OFPhysicalPort ofp = iofSwitch.getPort(port);
+        if (ofp == null) return;
+
+        int srcPortState = ofp.getState();
+        boolean portUp = ((srcPortState &
+                OFPortState.OFPPS_STP_MASK.getValue()) !=
+                OFPortState.OFPPS_STP_BLOCK.getValue());
+
+        if (portUp) operation = UpdateOperation.PORT_UP;
+        else operation = UpdateOperation.PORT_DOWN;
+
+        updates.add(new LDUpdate(sw, port, operation));
+    }
+
     /** 
-     * Send LLDP and BDDP on known 
+     * Send LLDP on known ports
      */
     protected void discoverOnKnownLinkPorts() {
         // Copy the port set.
@@ -332,10 +483,7 @@ IFloodlightModule, IInfoProvider, IHAListener {
     }
 
     protected void discover(long sw, short port) {
-        // Send standard lldp first
         sendDiscoveryMessage(sw, port, true, false);
-        // Then send the bddp following that.
-        sendDiscoveryMessage(sw, port, false, false);
     }
 
     /**
@@ -398,7 +546,6 @@ IFloodlightModule, IInfoProvider, IHAListener {
         // through provider and TPMR bridges (see IEEE 802.1AB-2009 and 802.1Q-2011),
         // in particular the Linux bridge which behaves mostly like a provider bridge
 
-
         ethernet.setPayload(lldp);
         byte[] chassisId = new byte[] {4, 0, 0, 0, 0, 0, 0}; // filled in later
         byte[] portId = new byte[] {2, 0, 0}; // filled in later
@@ -485,20 +632,18 @@ IFloodlightModule, IInfoProvider, IHAListener {
             IOFSwitch iofSwitch = floodlightProvider.getSwitches().get(sw);
             if (iofSwitch == null) continue;
             if (iofSwitch.getEnabledPorts() != null) {
-                for (OFPhysicalPort p : iofSwitch.getEnabledPorts()) {
+                for (short p: iofSwitch.getEnabledPorts()) {
                     // sends only forward LLDPs and BDDPs
-                    sendDiscoveryMessage(sw, p.getPortNumber(), true, false);
-                }
-            }
-        }
-
-        for (long sw: switches) {
-            IOFSwitch iofSwitch = floodlightProvider.getSwitches().get(sw);
-            if (iofSwitch == null) continue;
-            if (iofSwitch.getEnabledPorts() != null) {
-                for (OFPhysicalPort p : iofSwitch.getEnabledPorts()) {
-                    // sends only forward LLDPs and BDDPs
-                    sendDiscoveryMessage(sw, p.getPortNumber(), false, false);
+                    OFPhysicalPort ofp = iofSwitch.getPort(p);
+                    if (ofp==null) continue;
+                    sendDiscoveryMessage(sw, ofp.getPortNumber(), true, false);
+
+                    NodePortTuple npt = new NodePortTuple(sw, p);
+                    if (portLinks.containsKey(npt) == false ||
+                            portBroadcastDomainLinks.containsKey(npt)) {
+                        // add to maintenance list.
+                        addToMaintenanceQueue(npt);
+                    }
                 }
             }
         }
@@ -539,8 +684,6 @@ IFloodlightModule, IInfoProvider, IHAListener {
         this.controllerTLV = new LLDPTLV().setType((byte) 0x0c).setLength((short) controllerTLVValue.length).setValue(controllerTLVValue);
     }
 
-
-
     @Override
     public String getName() {
         return "linkdiscovery";
@@ -700,6 +843,28 @@ IFloodlightModule, IInfoProvider, IHAListener {
             }
         }
 
+        // If the received packet is a BDDP packet, then create a reverse BDDP
+        // link as well.
+        if (!isStandard) {
+            Link reverseLink = new Link(lt.getDst(), lt.getDstPort(),
+                                        lt.getSrc(), lt.getSrcPort());
+
+            // srcPortState and dstPort state are reversed.
+            LinkInfo reverseInfo =
+                    new LinkInfo(firstSeenTime, lastLldpTime, lastBddpTime,
+                                 dstPortState, srcPortState);
+
+            addOrUpdateLink(reverseLink, reverseInfo);
+        }
+
+        // Remove the node ports from the quarantine and maintenance queues.
+        NodePortTuple nptSrc = new NodePortTuple(lt.getSrc(), lt.getSrcPort());
+        NodePortTuple nptDst = new NodePortTuple(lt.getDst(), lt.getDstPort());
+        removeFromQuarantineQueue(nptSrc);
+        removeFromMaintenanceQueue(nptSrc);
+        removeFromQuarantineQueue(nptDst);
+        removeFromMaintenanceQueue(nptDst);
+
         // Consume this message
         return Command.STOP;
     }
@@ -724,6 +889,11 @@ IFloodlightModule, IInfoProvider, IHAListener {
                 return Command.STOP;
             }
         }
+
+        // If packet-in is from a quarantine port, stop processing.
+        NodePortTuple npt = new NodePortTuple(sw, pi.getInPort());
+        if (quarantineQueue.contains(npt)) return Command.STOP;
+
         return Command.CONTINUE;
     }
 
@@ -741,6 +911,8 @@ IFloodlightModule, IInfoProvider, IHAListener {
         return UpdateOperation.LINK_REMOVED;
     }
 
+
+
     protected UpdateOperation getUpdateOperation(int srcPortState) {
         boolean portUp = ((srcPortState &
                 OFPortState.OFPPS_STP_MASK.getValue()) !=
@@ -925,10 +1097,11 @@ IFloodlightModule, IInfoProvider, IHAListener {
                         this.portLinks.remove(dstNpt);
                 }
 
-                this.links.remove(lt);
+                LinkInfo info = this.links.remove(lt);
                 updates.add(new LDUpdate(lt.getSrc(), lt.getSrcPort(),
                                          lt.getDst(), lt.getDstPort(),
-                                         null, UpdateOperation.LINK_REMOVED));
+                                         getLinkType(lt, info),
+                                         UpdateOperation.LINK_REMOVED));
 
                 // Update Event History
                 evHistTopoLink(lt.getSrc(),
@@ -1070,15 +1243,13 @@ IFloodlightModule, IInfoProvider, IHAListener {
      */
     @Override
     public void addedSwitch(IOFSwitch sw) {
-        // It's probably overkill to send LLDP from all switches, but we don't
-        // know which switches might be connected to the new switch.
-        // Need to optimize when supporting a large number of switches.
-        NodePortTuple npt;
 
+        NodePortTuple npt;
         if (sw.getEnabledPorts() != null) {
-            for (OFPhysicalPort p : sw.getEnabledPorts()) {
-                npt = new NodePortTuple(sw.getId(), p.getPortNumber());
+            for (Short p : sw.getEnabledPorts()) {
+                npt = new NodePortTuple(sw.getId(), p);
                 discover(npt);
+                addToQuarantineQueue(npt);
             }
         }
         // Update event history
@@ -1543,6 +1714,9 @@ IFloodlightModule, IInfoProvider, IHAListener {
                 Collections.synchronizedSet(new HashSet<NodePortTuple>());
         this.portBroadcastDomainLinks = new HashMap<NodePortTuple, Set<Link>>();
         this.switchLinks = new HashMap<Long, Set<Link>>();
+        this.quarantineQueue = new LinkedBlockingQueue<NodePortTuple>();
+        this.maintenanceQueue = new LinkedBlockingQueue<NodePortTuple>();
+
         this.evHistTopologySwitch =
                 new EventHistory<EventHistoryTopologySwitch>("Topology: Switch");
         this.evHistTopologyLink =
@@ -1599,6 +1773,20 @@ IFloodlightModule, IInfoProvider, IHAListener {
             }
         });
 
+        // null role implies HA mode is not enabled.
+        Role role = floodlightProvider.getRole();
+        if (role == null || role == Role.MASTER) {
+            log.trace("Setup: Rescheduling discovery task. role = {}", role);
+            discoveryTask.reschedule(DISCOVERY_TASK_INTERVAL, TimeUnit.SECONDS);
+        } else {
+                log.trace("Setup: Not scheduling LLDP as role = {}.", role);
+        }
+
+        // Setup the BDDP task.  It is invoked whenever switch port tuples
+        // are added to the quarantine list.
+        bddpTask = new SingletonTask(ses, new QuarantineWorker());
+        bddpTask.reschedule(BDDP_TASK_INTERVAL, TimeUnit.MILLISECONDS);
+
         updatesThread = new Thread(new Runnable () {
             @Override
             public void run() {
@@ -1612,14 +1800,8 @@ IFloodlightModule, IInfoProvider, IHAListener {
             }}, "Topology Updates");
         updatesThread.start();
 
-        // null role implies HA mode is not enabled.
-        Role role = floodlightProvider.getRole();
-        if (role == null || role == Role.MASTER) {
-            log.trace("Setup: Rescheduling discovery task. role = {}", role);
-            discoveryTask.reschedule(DISCOVERY_TASK_INTERVAL, TimeUnit.SECONDS);
-        } else {
-                log.trace("Setup: Not scheduling LLDP as role = {}.", role);
-        }
+
+
         // Register for the OpenFlow messages we want to receive
         floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
         floodlightProvider.addOFMessageListener(OFType.PORT_STATUS, this);
diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
index 82a67fec4062512367ddeca22e1b5a7242db62a1..cc62e82ac86f78eb63c20da7b70833d5786248e7 100644
--- a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
+++ b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
@@ -91,8 +91,8 @@ public interface ITopologyService extends IFloodlightService  {
      * @param sw The switch DPID in long
      * @return The set of ports on this switch
      */
-    public Set<Short> getPorts(long sw);
-    public Set<Short> getPorts(long sw, boolean tunnelEnabled);
+    public Set<Short> getPortsWithLinks(long sw);
+    public Set<Short> getPortsWithLinks(long sw, boolean tunnelEnabled);
 
     /** Get broadcast ports on a target switch for a given attachmentpoint
      * point port.
@@ -101,7 +101,7 @@ public interface ITopologyService extends IFloodlightService  {
 
     public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort,
                                         boolean tunnelEnabled);
-    
+
     /**
      * 
      */
@@ -166,15 +166,15 @@ public interface ITopologyService extends IFloodlightService  {
                                     short srcPort,
                                     boolean tunnelEnabled);
 
-    
+
     /**
      * Gets the set of ports that belong to a broadcast domain.
      * @return The set of ports that belong to a broadcast domain.
      */
     public Set<NodePortTuple> getBroadcastDomainPorts();
     public Set<NodePortTuple> getTunnelPorts();
-    
-    
+
+
     /**
      * Returns a set of blocked ports.  The set of blocked
      * ports is the union of all the blocked ports across all
@@ -182,7 +182,7 @@ public interface ITopologyService extends IFloodlightService  {
      * @return
      */
     public Set<NodePortTuple> getBlockedPorts();
-    
+
     /**
      * ITopologyListener provides topologyChanged notification, 
      * but not *what* the changes were.  
@@ -190,4 +190,9 @@ public interface ITopologyService extends IFloodlightService  {
      * @return
      */
     public List<LDUpdate> getLastLinkUpdates();
+
+    /**
+     * Switch methods
+     */
+    public Set<Short> getPorts(long sw);
 }
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
index 298c49861236391997dd8adcf72f12d85d89af1e..1d24cf3e04c1038465cf2e01c8c9db65c9ce346c 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
@@ -741,7 +741,7 @@ public class TopologyInstance {
         return switches;
     }
 
-    public Set<Short> getPorts(long sw) {
+    public Set<Short> getPortsWithLinks(long sw) {
         return switchPorts.get(sw);
     }
 
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index 71751f9950738f9a58460927c8175322ab08cb9a..27cae7298be228e3badcdbf856509afb89ca84d6 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -62,15 +62,20 @@ public class TopologyManager implements
             "com.bigswitch.floodlight.topologymanager.tunnelEnabled";
 
     /** 
-     * Set of ports for each switch 
+     * Set of ports for each switch
      */
-    protected Map<Long, Set<Short>> switchPorts; 
+    protected Map<Long, Set<Short>> 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.
      */
@@ -80,6 +85,7 @@ public class TopologyManager implements
      * set of tunnel links
      */
     protected Map<NodePortTuple, Set<Link>> tunnelLinks; 
+
     protected ILinkDiscoveryService linkDiscovery;
     protected IThreadPoolService threadPool;
     protected IFloodlightProviderService floodlightProvider;
@@ -97,19 +103,17 @@ public class TopologyManager implements
     
     protected SingletonTask newInstanceTask;
     private Date lastUpdateTime;
+    protected boolean recomputeTopologyFlag;
 
     /**
      * Thread for recomputing topology.  The thread is always running, 
      * however the function applyUpdates() has a blocking call.
      */
-    protected class NewInstanceWorker implements Runnable {
+    protected class UpdateTopologyWorker implements Runnable {
         @Override 
         public void run() {
             try {
-                applyUpdates();
-                createNewInstance();
-                lastUpdateTime = new Date();
-                informListeners();
+                updateTopology();
             }
             catch (Exception e) {
                 log.error("Error in topology instance task thread", e);
@@ -117,6 +121,15 @@ public class TopologyManager implements
         }
     }
 
+    public boolean updateTopology() {
+        recomputeTopologyFlag = false;
+        applyUpdates();
+        createNewInstance();
+        lastUpdateTime = new Date();
+        informListeners();
+        return recomputeTopologyFlag;
+    }
+
     // **********************
     // ILinkDiscoveryListener
     // **********************
@@ -241,15 +254,15 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     /** Get all the ports connected to the switch */
     @Override
-    public Set<Short> getPorts(long sw) {
-        return getPorts(sw, true);
+    public Set<Short> getPortsWithLinks(long sw) {
+        return getPortsWithLinks(sw, true);
     }
 
     /** Get all the ports connected to the switch */
     @Override
-    public Set<Short> getPorts(long sw, boolean tunnelEnabled) {
+    public Set<Short> getPortsWithLinks(long sw, boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
-        return ti.getPorts(sw);
+        return ti.getPortsWithLinks(sw);
     }
 
     ////////////////////////////////////////////////////////////////////////
@@ -613,6 +626,7 @@ public class TopologyManager implements
 
         switchPorts = new HashMap<Long,Set<Short>>();
         switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
+        directLinks = new HashMap<NodePortTuple, Set<Link>>();
         portBroadcastDomainLinks = new HashMap<NodePortTuple, Set<Link>>();
         tunnelLinks = new HashMap<NodePortTuple, Set<Link>>();
         topologyAware = new ArrayList<ITopologyListener>();
@@ -624,7 +638,7 @@ public class TopologyManager implements
     @Override
     public void startUp(FloodlightModuleContext context) {
         ScheduledExecutorService ses = threadPool.getScheduledExecutor();
-        newInstanceTask = new SingletonTask(ses, new NewInstanceWorker());
+        newInstanceTask = new SingletonTask(ses, new UpdateTopologyWorker());
         linkDiscovery.addListener(this);
         floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
         floodlightProvider.addHAListener(this);
@@ -753,13 +767,13 @@ public class TopologyManager implements
             IOFSwitch sw = floodlightProvider.getSwitches().get(sid);
             if (sw == null) continue;
             Set<Short> ports = new HashSet<Short>();
-            if (sw.getPorts() == null) continue;
-            ports.addAll(sw.getPorts().keySet());
+            if (sw.getEnabledPorts() == null) continue;
+            ports.addAll(sw.getEnabledPorts());
 
             // 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<Short> portsKnownToTopo = ti.getPorts(sid);
+            Set<Short> portsKnownToTopo = ti.getPortsWithLinks(sid);
 
             if (portsKnownToTopo != null) {
                 for(short p: portsKnownToTopo) {
@@ -798,7 +812,6 @@ public class TopologyManager implements
         return Command.STOP;
     }
 
-
     public void applyUpdates() {
 
         appliedUpdates.clear();
@@ -834,13 +847,15 @@ public class TopologyManager implements
      * This function computes a new topology.
      */
     /**
-     * This function computes a new topology intance.
+     * This function computes a new topology instance.
      * It ignores links connected to all broadcast domain ports
      * and tunnel ports.
      */
-    public void createNewInstance() {
+    protected void createNewInstance() {
         Set<NodePortTuple> blockedPorts = new HashSet<NodePortTuple>();
 
+        if (!recomputeTopologyFlag) return;
+
         Map<NodePortTuple, Set<Link>> openflowLinks;
         openflowLinks = 
                 new HashMap<NodePortTuple, Set<Link>>(switchPortLinks);
@@ -920,6 +935,13 @@ public class TopologyManager implements
         return true;
     }
 
+    /**
+     * Add the given link to the data structure.  Returns true if a link was
+     * added.
+     * @param s
+     * @param l
+     * @return
+     */
     private boolean addLinkToStructure(Map<NodePortTuple, 
                                        Set<Link>> s, Link l) {
         boolean result1 = false, result2 = false; 
@@ -928,17 +950,24 @@ public class TopologyManager implements
         NodePortTuple n2 = new NodePortTuple(l.getDst(), l.getDstPort());
 
         if (s.get(n1) == null) {
-            s.put(n1, new HashSet<Link>()); 
+            s.put(n1, new HashSet<Link>());
         }
         if (s.get(n2) == null) {
-            s.put(n2, new HashSet<Link>()); 
+            s.put(n2, new HashSet<Link>());
         }
         result1 = s.get(n1).add(l);
         result2 = s.get(n2).add(l);
 
-        return (result1 && result2);
+        return (result1 || result2);
     }
 
+    /**
+     * Delete the given link from the data strucure.  Returns true if the
+     * link was deleted.
+     * @param s
+     * @param l
+     * @return
+     */
     private boolean removeLinkFromStructure(Map<NodePortTuple, 
                                             Set<Link>> s, Link l) {
 
@@ -954,13 +983,14 @@ public class TopologyManager implements
             result2 = s.get(n2).remove(l);
             if (s.get(n2).isEmpty()) s.remove(n2);
         }
-        return result1 && result2; 
+        return result1 || result2;
     }
 
     public void addOrUpdateLink(long srcId, short srcPort, long dstId, 
                                 short dstPort, LinkType type) {
-        Link link = new Link(srcId, srcPort, dstId, dstPort);
+        boolean flag1 = false, flag2 = false;
 
+        Link link = new Link(srcId, srcPort, dstId, dstPort);
         addPortToSwitch(srcId, srcPort);
         addPortToSwitch(dstId, dstPort);
 
@@ -968,19 +998,31 @@ public class TopologyManager implements
 
         if (type.equals(LinkType.MULTIHOP_LINK)) {
             addLinkToStructure(portBroadcastDomainLinks, link);
-            removeLinkFromStructure(tunnelLinks, link);
+            flag1 = removeLinkFromStructure(tunnelLinks, link);
+            flag2 = removeLinkFromStructure(directLinks, link);
+            recomputeTopologyFlag = flag1 || flag2;
         } else if (type.equals(LinkType.TUNNEL)) {
             addLinkToStructure(tunnelLinks, link);
             removeLinkFromStructure(portBroadcastDomainLinks, link);
+            removeLinkFromStructure(directLinks, link);
+            recomputeTopologyFlag = true;
         } else if (type.equals(LinkType.DIRECT_LINK)) {
+            addLinkToStructure(directLinks, link);
             removeLinkFromStructure(tunnelLinks, link);
             removeLinkFromStructure(portBroadcastDomainLinks, link);
+            recomputeTopologyFlag = true;
         }
     }
 
     public void removeLink(Link link)  {
+        boolean flag1 = false, flag2 = false;
+
+        flag1 = removeLinkFromStructure(directLinks, link);
+        flag2 = removeLinkFromStructure(tunnelLinks, link);
+
+        recomputeTopologyFlag = flag1 || flag2;
+
         removeLinkFromStructure(portBroadcastDomainLinks, link);
-        removeLinkFromStructure(tunnelLinks, link);
         removeLinkFromStructure(switchPortLinks, link);
 
         NodePortTuple srcNpt = 
@@ -1020,6 +1062,7 @@ public class TopologyManager implements
         switchPortLinks.clear();
         portBroadcastDomainLinks.clear();
         tunnelLinks.clear();
+        directLinks.clear();
         appliedUpdates.clear();
     }
 
@@ -1057,5 +1100,23 @@ public class TopologyManager implements
     public TopologyInstance getCurrentInstance() {
         return this.getCurrentInstance(true);
     }
-}
 
+    /**
+     *  Switch methods
+     */
+    public Set<Short> getPorts(long sw) {
+        Set<Short> ports = new HashSet<Short>();
+        IOFSwitch iofSwitch = floodlightProvider.getSwitches().get(sw);
+        if (iofSwitch == null) return null;
+
+        List<Short> ofpList = iofSwitch.getEnabledPorts();
+        if (ofpList == null) return null;
+
+        Set<Short> qPorts = linkDiscovery.getQuarantinedPorts(sw);
+        if (qPorts != null)
+            ofpList.removeAll(qPorts);
+
+        ports.addAll(ofpList);
+        return ports;
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
index a6b6d6abc82308ca139036eaab1cc2d4f458e74c..df4d8e7ca069643094a1909fabdbd8bec4113e99 100644
--- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
+++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
@@ -700,6 +700,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
                                          EasyMock.anyLong(),
                                          EasyMock.anyShort())).andReturn(false).
                                          anyTimes();
+        expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes();
         replay(mockTopology);
 
         Date currentDate = new Date();
@@ -1259,6 +1260,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         expect(mockTopology.isAttachmentPointPort(anyLong(),
                                                   anyShort())).
                                                   andReturn(true).anyTimes();
+        expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes();
         replay(mockTopology);
         doTestDeviceQuery();
     }
@@ -1270,6 +1272,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         expect(mockTopology.isAttachmentPointPort(anyLong(),
                                                   anyShort())).
                                                   andReturn(true).anyTimes();
+        expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes();
         replay(mockTopology);
         
         doTestDeviceQuery();
@@ -1339,6 +1342,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         expect(mockTopology.isAttachmentPointPort(anyLong(),
                                                   anyShort())).
                                                   andReturn(true).anyTimes();
+        expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes();
         replay(mockTopology);
 
         doTestDeviceClassQuery();
@@ -1351,11 +1355,12 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         expect(mockTopology.isAttachmentPointPort(anyLong(),
                                                   anyShort())).
                                                   andReturn(true).anyTimes();
+        expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes();
         replay(mockTopology);
 
         doTestDeviceClassQuery();
     }
-    
+
     @Test
     public void testFindDevice() {
         boolean exceptionCaught;
@@ -1367,6 +1372,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         expect(mockTopology.isAttachmentPointPort(anyLong(),
                                                   anyShort())).
                                                   andReturn(true).anyTimes();
+        expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes();
         replay(mockTopology);
 
         Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date());
diff --git a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java
index e2f1e7d31ac18e4fa397d67b6cd33c5340845730..4f474da897c47413da975f05a8711d5bb9482e95 100644
--- a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java
+++ b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java
@@ -373,6 +373,7 @@ public class ForwardingTest extends FloodlightTestCase {
         reset(topology);
         expect(topology.isAttachmentPointPort(EasyMock.anyLong(), EasyMock.anyShort()))
         .andReturn(true).anyTimes();
+        expect(topology.getL2DomainId(1L)).andReturn(1L).anyTimes();
         replay(topology);
 
         srcDevice =