diff --git a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java
index fd20d387e3dd4fb68bbf2e1bd406201d807c5f01..b8d8e0bf9e34c73113c0aa955edaa5443aa18eef 100644
--- a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java
@@ -62,16 +62,24 @@ public class ControllerSwitchesResource extends ServerResource {
 
         public Map<String,String> getDescription() {
             Map<String,String> rv = new HashMap<String, String>();
-            rv.put("manufacturer",
-                   sw.getDescriptionStatistics().getManufacturerDescription());
-            rv.put("hardware",
-                   sw.getDescriptionStatistics().getHardwareDescription());
-            rv.put("software",
-                   sw.getDescriptionStatistics().getSoftwareDescription());
-            rv.put("serialNum",
-                   sw.getDescriptionStatistics().getSerialNumber());
-            rv.put("datapath",
-                   sw.getDescriptionStatistics().getDatapathDescription());
+            if (sw.getDescriptionStatistics() == null) {
+                rv.put("manufacturer", "");
+                rv.put("hardware", "");
+                rv.put("software", "");
+                rv.put("serialNum", "");
+                rv.put("datapath", "");
+            } else {
+                rv.put("manufacturer",
+                       sw.getDescriptionStatistics().getManufacturerDescription());
+                rv.put("hardware",
+                       sw.getDescriptionStatistics().getHardwareDescription());
+                rv.put("software",
+                       sw.getDescriptionStatistics().getSoftwareDescription());
+                rv.put("serialNum",
+                       sw.getDescriptionStatistics().getSerialNumber());
+                rv.put("datapath",
+                       sw.getDescriptionStatistics().getDatapathDescription());
+            }
             return rv;
         }
 
@@ -92,6 +100,8 @@ public class ControllerSwitchesResource extends ServerResource {
         }
 
         public String getHarole() {
+            if (sw.getHARole() == null)
+                return "null";
             return sw.getHARole().toString();
         }
 
diff --git a/src/main/java/net/floodlightcontroller/debugevent/Event.java b/src/main/java/net/floodlightcontroller/debugevent/Event.java
index ebbeb650ff771b8040074c589c4ffcd438afae42..28c242a07a5273e0db658f5be1ab1b8e3df5ed34 100644
--- a/src/main/java/net/floodlightcontroller/debugevent/Event.java
+++ b/src/main/java/net/floodlightcontroller/debugevent/Event.java
@@ -1,12 +1,15 @@
 package net.floodlightcontroller.debugevent;
 
+import java.lang.ref.SoftReference;
 import java.lang.reflect.Field;
 import java.text.SimpleDateFormat;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
 import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType;
+import net.floodlightcontroller.devicemanager.SwitchPort;
 import net.floodlightcontroller.packet.IPv4;
 
 import org.openflow.util.HexString;
@@ -129,14 +132,95 @@ public class Event {
             f.setAccessible(true);
             try {
                 Object obj =  f.get(eventData);
-                if (ec.description() == EventFieldType.DPID) {
-                    retMap.put(ec.name(), HexString.toHexString((Long) obj));
-                } else if (ec.description() == EventFieldType.MAC) {
-                    retMap.put(ec.name(), HexString.toHexString((Long) obj, 6));
-                } else if (ec.description() == EventFieldType.IPv4) {
-                    retMap.put(ec.name(), IPv4.fromIPv4Address((Integer) obj));
-                } else {
-                    retMap.put(ec.name(), obj.toString());
+
+                switch(ec.description()) {
+                    case DPID:
+                        retMap.put(ec.name(), HexString.toHexString((Long) obj));
+                        break;
+                    case MAC:
+                        retMap.put(ec.name(), HexString.toHexString((Long) obj, 6));
+                        break;
+                    case IPv4:
+                        retMap.put(ec.name(), IPv4.fromIPv4Address((Integer) obj));
+                        break;
+                    case LIST_IPV4:
+                        @SuppressWarnings("unchecked")
+                        List<Integer> ipv4Addresses = (List<Integer>)obj;
+                        StringBuilder ipv4AddressesStr = new StringBuilder();
+                        if (ipv4Addresses.size() == 0) {
+                            ipv4AddressesStr.append("--");
+                        } else {
+                            for (Integer ipv4Addr : ipv4Addresses) {
+                                ipv4AddressesStr.append(IPv4.fromIPv4Address(ipv4Addr.intValue()));
+                                ipv4AddressesStr.append(" ");
+                            }
+                        }
+                        retMap.put(ec.name(), ipv4AddressesStr.toString());
+                        break;
+                    case LIST_ATTACHMENT_POINT:
+                        @SuppressWarnings("unchecked")
+                        List<SwitchPort> aps = (List<SwitchPort>)obj;
+                        StringBuilder apsStr = new StringBuilder();
+                        if (aps.size() == 0) {
+                            apsStr.append("--");
+                        } else {
+                            for (SwitchPort ap : aps) {
+                                apsStr.append(HexString.toHexString(ap.getSwitchDPID()));
+                                apsStr.append("/");
+                                apsStr.append(ap.getPort());
+                                apsStr.append(" ");
+                            }
+                        }
+                        retMap.put(ec.name(), apsStr.toString());
+                        break;
+                    case LIST_OBJECT:
+                        @SuppressWarnings("unchecked")
+                        List<Object> obl = (List<Object>)obj;
+                        StringBuilder sbldr = new StringBuilder();
+                        if (obl.size() == 0) {
+                            sbldr.append("--");
+                        } else {
+                            for (Object o : obl) {
+                                sbldr.append(o.toString());
+                                sbldr.append(" ");
+                            }
+                        }
+                        retMap.put(ec.name(), sbldr.toString());
+                        break;
+                    case SREF_LIST_OBJECT:
+                        @SuppressWarnings("unchecked")
+                        SoftReference<List<Object>> srefListObj =
+                            (SoftReference<List<Object>>)obj;
+                        List<Object> ol = srefListObj.get();
+                        if (ol != null) {
+                            StringBuilder sb = new StringBuilder();
+                            if (ol.size() == 0) {
+                                sb.append("--");
+                            } else {
+                                for (Object o : ol) {
+                                    sb.append(o.toString());
+                                    sb.append(" ");
+                                }
+                            }
+                            retMap.put(ec.name(), sb.toString());
+                        } else {
+                            retMap.put(ec.name(), "-- reference not available --");
+                        }
+                        break;
+                    case SREF_OBJECT:
+                        @SuppressWarnings("unchecked")
+                        SoftReference<Object> srefObj = (SoftReference<Object>)obj;
+                        Object o = srefObj.get();
+                        if (o != null) {
+                            retMap.put(ec.name(), o.toString());
+                        } else {
+                            retMap.put(ec.name(), "-- reference not available --");
+                        }
+                    case STRING:
+                    case OBJECT:
+                    case PRIMITIVE:
+                    default:
+                        retMap.put(ec.name(), obj.toString());
                 }
             } catch (ClassCastException e) {
                 retMap.put("Error", e.getMessage());
diff --git a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java
index 7146c8ffe236e23dd330df2b5c739871f8ac7c5d..300f8fa096b9fe98bb45801fd3fb7517f7791757 100644
--- a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java
+++ b/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java
@@ -25,7 +25,8 @@ public interface IDebugEventService extends IFloodlightService {
      * Describes the type of field obtained from reflection
      */
     enum EventFieldType {
-        DPID, IPv4, MAC, STRING, OBJECT, PRIMITIVE
+        DPID, IPv4, MAC, STRING, OBJECT, PRIMITIVE, LIST_IPV4,
+        LIST_ATTACHMENT_POINT, LIST_OBJECT, SREF_LIST_OBJECT, SREF_OBJECT,
     }
 
     /**
@@ -89,7 +90,7 @@ public interface IDebugEventService extends IFloodlightService {
      *                         be explicitly enabled using other methods in this API
      * @param eventClass       A user defined class that annotates the fields
      *                         with @EventColumn. This class specifies the
-     *                         fields/columns of this event.
+     *                         fields/columns for this event.
      * @param bufferCapacity   Number of events to store for this event in a circular
      *                         buffer. Older events will be discarded once the
      *                         buffer is full.
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
index 457bb564405d1e6bedbd7eda6fe682438163cc98..ef0ba346809496090c83e273be35c5576699369c 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
@@ -464,14 +464,11 @@ public class Device implements IDevice {
         } else  if (oldAPFlag) {
             // retain oldAP  as is.  Put the newAP in oldAPs for flagging
             // possible duplicates.
-            oldAPList = new ArrayList<AttachmentPoint>();
-            if (oldAPs != null) oldAPList.addAll(oldAPs);
-            // Add to oldAPList only if it was picked up from the oldAPList
-            oldAPList.add(newAP);
-            this.oldAPs = oldAPList;
-            if (!topology.isInSameBroadcastDomain(oldAP.getSw(), oldAP.getPort(),
-                                                  newAP.getSw(), newAP.getPort()))
-                return true; // attachment point changed.
+                oldAPList = new ArrayList<AttachmentPoint>();
+                if (oldAPs != null) oldAPList.addAll(oldAPs);
+                // Add ot oldAPList only if it was picked up from the oldAPList
+                oldAPList.add(newAP);
+                this.oldAPs = oldAPList;
         }
         return false;
     }
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index 5223fb6ed1ad6a47749510bb1f7715dde9dfd2e0..276e6629f9ac9f539179631503a7e02d48e45701 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -18,6 +18,7 @@
 package net.floodlightcontroller.devicemanager.internal;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
@@ -57,6 +58,13 @@ import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
 import net.floodlightcontroller.debugcounter.NullDebugCounter;
 import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
+import net.floodlightcontroller.debugevent.IDebugEventService;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventType;
+import net.floodlightcontroller.debugevent.IDebugEventService.MaxEventsRegistered;
+import net.floodlightcontroller.debugevent.IEventUpdater;
+import net.floodlightcontroller.debugevent.NullDebugEvent;
 import net.floodlightcontroller.devicemanager.IDevice;
 import net.floodlightcontroller.devicemanager.IDeviceService;
 import net.floodlightcontroller.devicemanager.IEntityClass;
@@ -162,6 +170,12 @@ IFlowReconcileListener, IInfoProvider {
     public IDebugCounter cntConsolidateStoreDevicesRemoved;
     public IDebugCounter cntTransitionToMaster;
 
+    /**
+     * Debug Events
+     */
+    private IDebugEventService debugEvents;
+    private IEventUpdater<DeviceEvent> evDevice;
+
     private boolean isMaster = false;
 
     static final String DEVICE_SYNC_STORE_NAME =
@@ -659,6 +673,69 @@ IFlowReconcileListener, IInfoProvider {
         }
     }
 
+    // ***************
+    // IDeviceListener
+    // ***************
+    private class DeviceDebugEventLogger implements IDeviceListener {
+        @Override
+        public String getName() {
+            return "deviceDebugEventLogger";
+        }
+
+        @Override
+        public boolean isCallbackOrderingPrereq(String type, String name) {
+            return false;
+        }
+
+        @Override
+        public boolean isCallbackOrderingPostreq(String type, String name) {
+            return false;
+        }
+
+        @Override
+        public void deviceAdded(IDevice device) {
+            generateDeviceEvent(device, "host-added");
+        }
+
+        @Override
+        public void deviceRemoved(IDevice device) {
+            generateDeviceEvent(device, "host-removed");
+        }
+
+        @Override
+        public void deviceMoved(IDevice device) {
+            generateDeviceEvent(device, "host-moved");
+        }
+
+        @Override
+        public void deviceIPV4AddrChanged(IDevice device) {
+            generateDeviceEvent(device, "host-ipv4-addr-changed");
+        }
+
+        @Override
+        public void deviceVlanChanged(IDevice device) {
+            generateDeviceEvent(device, "host-vlan-changed");
+        }
+
+        private void generateDeviceEvent(IDevice device, String reason) {
+            List<Integer> ipv4Addresses =
+                new ArrayList<Integer>(Arrays.asList(device.getIPv4Addresses()));
+            List<SwitchPort> oldAps =
+                new ArrayList<SwitchPort>(Arrays.asList(device.getOldAP()));
+            List<SwitchPort> currentAps =
+                    new ArrayList<SwitchPort>(Arrays.asList(device.getAttachmentPoints()));
+            List<Short> vlanIds =
+                    new ArrayList<Short>(Arrays.asList(device.getVlanId()));
+
+            evDevice.updateEventNoFlush(
+                    new DeviceEvent(device.getMACAddress(),
+                                    ipv4Addresses,
+                                    oldAps,
+                                    currentAps,
+                                    vlanIds, reason));
+        }
+    }
+
     // *************
     // IInfoProvider
     // *************
@@ -832,10 +909,27 @@ IFlowReconcileListener, IInfoProvider {
         this.flowReconcileEngine = fmc.getServiceImpl(IFlowReconcileEngineService.class);
         this.entityClassifier = fmc.getServiceImpl(IEntityClassifierService.class);
         this.debugCounters = fmc.getServiceImpl(IDebugCounterService.class);
+        this.debugEvents = fmc.getServiceImpl(IDebugEventService.class);
         this.syncService = fmc.getServiceImpl(ISyncService.class);
         this.deviceSyncManager = new DeviceSyncManager();
         this.haListenerDelegate = new HAListenerDelegate();
         registerDeviceManagerDebugCounters();
+        registerDeviceManagerDebugEvents();
+        this.addListener(new DeviceDebugEventLogger());
+    }
+
+    private void registerDeviceManagerDebugEvents() throws FloodlightModuleException {
+        if (debugEvents == null) {
+            debugEvents = new NullDebugEvent();
+        }
+        try {
+            evDevice =
+                debugEvents.registerEvent(PACKAGE, "hostevent",
+                                          "Host added, removed, updated, or moved",
+                                          EventType.ALWAYS_LOG, DeviceEvent.class, 500);
+        } catch (MaxEventsRegistered e) {
+            throw new FloodlightModuleException("Max events registered", e);
+        }
     }
 
     @Override
@@ -2493,4 +2587,37 @@ IFlowReconcileListener, IInfoProvider {
     IHAListener getHAListener() {
         return this.haListenerDelegate;
     }
+
+    /**
+     * Device Event Class used to log Device related events
+     */
+    private class DeviceEvent {
+        @EventColumn(name = "MAC", description = EventFieldType.MAC)
+        private final long macAddress;
+        @EventColumn(name = "IPs", description = EventFieldType.LIST_IPV4)
+        private final List<Integer> ipv4Addresses;
+        @EventColumn(name = "Old Attachment Points",
+                     description = EventFieldType.LIST_ATTACHMENT_POINT)
+        private final List<SwitchPort> oldAttachmentPoints;
+        @EventColumn(name = "Current Attachment Points",
+                     description = EventFieldType.LIST_ATTACHMENT_POINT)
+        private final List<SwitchPort> currentAttachmentPoints;
+        @EventColumn(name = "VLAN IDs", description = EventFieldType.LIST_OBJECT)
+        private final List<Short> vlanIds;
+        @EventColumn(name = "Reason", description = EventFieldType.STRING)
+        private final String reason;
+
+        public DeviceEvent(long macAddress, List<Integer> ipv4Addresses,
+                List<SwitchPort> oldAttachmentPoints,
+                List<SwitchPort> currentAttachmentPoints,
+                List<Short> vlanIds, String reason) {
+            super();
+            this.macAddress = macAddress;
+            this.ipv4Addresses = ipv4Addresses;
+            this.oldAttachmentPoints = oldAttachmentPoints;
+            this.currentAttachmentPoints = currentAttachmentPoints;
+            this.vlanIds = vlanIds;
+            this.reason = reason;
+        }
+    }
 }
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
index 9b3cd7b871af7151a77644f6ff2be6ceab0a61ac..6231f837b043c68f9ea604f64139a008eaf56ee8 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
@@ -18,7 +18,6 @@
 package net.floodlightcontroller.linkdiscovery.internal;
 
 import java.io.IOException;
-import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.nio.ByteBuffer;
@@ -84,7 +83,6 @@ import net.floodlightcontroller.notification.INotificationManager;
 import net.floodlightcontroller.notification.NotificationManagerFactory;
 import net.floodlightcontroller.packet.BSN;
 import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPv4;
 import net.floodlightcontroller.packet.LLDP;
 import net.floodlightcontroller.packet.LLDPTLV;
 import net.floodlightcontroller.restserver.IRestApiService;
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index c92e4b710fd051c562ebb8f27aeb8b16d62fbade..961d6259cb49c1cb29cfc1e6f4da73db0983d860 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -51,6 +51,13 @@ import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
 import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
 import net.floodlightcontroller.debugcounter.NullDebugCounter;
+import net.floodlightcontroller.debugevent.IDebugEventService;
+import net.floodlightcontroller.debugevent.IEventUpdater;
+import net.floodlightcontroller.debugevent.NullDebugEvent;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventType;
+import net.floodlightcontroller.debugevent.IDebugEventService.MaxEventsRegistered;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
 import net.floodlightcontroller.packet.BSN;
@@ -164,6 +171,65 @@ public class TopologyManager implements
     protected static final String PACKAGE = TopologyManager.class.getPackage().getName();
     protected IDebugCounter ctrIncoming;
 
+    /**
+     * Debug Events
+     */
+    protected IDebugEventService debugEvents;
+
+    /*
+     * Topology Event Updater
+     */
+    protected IEventUpdater<TopologyEvent> evTopology;
+
+    /**
+     * Topology Information exposed for a Topology related event - used inside
+     * the BigTopologyEvent class
+     */
+    protected class TopologyEventInfo {
+        private final int numOpenflowClusters;
+        private final int numExternalClusters;
+        private final int numExternalPorts;
+        private final int numTunnelPorts;
+        public TopologyEventInfo(int numOpenflowClusters,
+                int numExternalClusters, int numExternalPorts,
+                int numTunnelPorts) {
+            super();
+            this.numOpenflowClusters = numOpenflowClusters;
+            this.numExternalClusters = numExternalClusters;
+            this.numExternalPorts = numExternalPorts;
+            this.numTunnelPorts = numTunnelPorts;
+        }
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("# Openflow Clusters: ");
+            builder.append(numOpenflowClusters);
+            builder.append(", # External Clusters: ");
+            builder.append(numExternalClusters);
+            builder.append(", # External Ports: ");
+            builder.append(numExternalPorts);
+            builder.append(", # Tunnel Ports: ");
+            builder.append(numTunnelPorts);
+            return builder.toString();
+        }
+    }
+
+    /**
+     * Topology Event class to track topology related events
+     */
+    protected class TopologyEvent {
+        @EventColumn(name = "Reason", description = EventFieldType.STRING)
+        private final String reason;
+        @EventColumn(name = "Topology Summary")
+        private final TopologyEventInfo topologyInfo;
+        public TopologyEvent(String reason,
+                TopologyEventInfo topologyInfo) {
+            super();
+            this.reason = reason;
+            this.topologyInfo = topologyInfo;
+        }
+    }
+
    //  Getter/Setter methods
     /**
      * Get the time interval for the period topology updates, if any.
@@ -221,7 +287,7 @@ public class TopologyManager implements
         dtLinksUpdated = false;
         tunnelPortsUpdated = false;
         List<LDUpdate> appliedUpdates = applyUpdates();
-        newInstanceFlag = createNewInstance();
+        newInstanceFlag = createNewInstance("link-discovery-updates");
         lastUpdateTime = new Date();
         informListeners(appliedUpdates);
         return newInstanceFlag;
@@ -762,6 +828,7 @@ public class TopologyManager implements
                 context.getServiceImpl(IFloodlightProviderService.class);
         restApi = context.getServiceImpl(IRestApiService.class);
         debugCounters = context.getServiceImpl(IDebugCounterService.class);
+        debugEvents = context.getServiceImpl(IDebugEventService.class);
 
         switchPorts = new HashMap<Long,Set<Short>>();
         switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
@@ -772,6 +839,22 @@ public class TopologyManager implements
         ldUpdates = new LinkedBlockingQueue<LDUpdate>();
         haListener = new HAListenerDelegate();
         registerTopologyDebugCounters();
+        registerTopologyDebugEvents();
+    }
+
+    protected void registerTopologyDebugEvents() throws FloodlightModuleException {
+        if (debugEvents == null) {
+            debugEvents = new NullDebugEvent();
+        }
+        try {
+            evTopology =
+                debugEvents.registerEvent(PACKAGE, "topologyevent",
+                                          "Topology Computation",
+                                          EventType.ALWAYS_LOG,
+                                          TopologyEvent.class, 100);
+        } catch (MaxEventsRegistered e) {
+            throw new FloodlightModuleException("Max events registered", e);
+        }
     }
 
     @Override
@@ -1084,13 +1167,17 @@ public class TopologyManager implements
         tunnelPortsUpdated = true;
     }
 
+    public boolean createNewInstance() {
+        return createNewInstance("internal");
+    }
+
     /**
      * This function computes a new topology instance.
      * It ignores links connected to all broadcast domain ports
      * and tunnel ports. The method returns if a new instance of
      * topology was created or not.
      */
-    protected boolean createNewInstance() {
+    protected boolean createNewInstance(String reason) {
         Set<NodePortTuple> blockedPorts = new HashSet<NodePortTuple>();
 
         if (!linksUpdated) return false;
@@ -1140,6 +1227,11 @@ public class TopologyManager implements
         // If needed, we may compute them differently.
         currentInstance = nt;
         currentInstanceWithoutTunnels = nt;
+
+        TopologyEventInfo topologyInfo =
+                new TopologyEventInfo(nt.getClusters().size(), 0, 0, 0);
+        evTopology.updateEventWithFlush(new TopologyEvent(reason,
+                                                          topologyInfo));
         return true;
     }
 
@@ -1388,7 +1480,7 @@ public class TopologyManager implements
         linksUpdated = true;
         dtLinksUpdated = true;
         tunnelPortsUpdated = true;
-        createNewInstance();
+        createNewInstance("startup");
         lastUpdateTime = new Date();
     }
 
diff --git a/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java b/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java
index 5fbaba9d47ab0031a5792c822d6721f2314d0efe..e48a816db38a68ed339c327867831410e484d63a 100644
--- a/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java
+++ b/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java
@@ -9,7 +9,6 @@ import net.floodlightcontroller.debugevent.IDebugEventService.DebugEventInfo;
 import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
 import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType;
 import net.floodlightcontroller.debugevent.IDebugEventService.EventType;
-import net.floodlightcontroller.debugevent.IDebugEventService.MaxEventsRegistered;
 import net.floodlightcontroller.test.FloodlightTestCase;
 
 public class DebugEventTest extends FloodlightTestCase {
diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
index 36a844d1c251f0d10b963460a432303ec077a0da..ecd145f969176aafb8e7a0ede3dcbc87bd5fb731 100644
--- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
+++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
@@ -661,6 +661,106 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         verify(mockListener);
     }
 
+    /**
+     * In this test, a device is moved from attachment point (1,1) to (5,1)
+     * and then moved back to (1,1) within 30 seconds.  Both the moves should
+     * generate device moved notification.
+     * @throws Exception
+     */
+    @Test
+    public void testAttachmentPointMovingBack() throws Exception {
+        IDeviceListener mockListener =
+                createMock(IDeviceListener.class);
+        expect(mockListener.getName()).andReturn("mockListener").atLeastOnce();
+        expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject()))
+        .andReturn(false).atLeastOnce();
+        expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject()))
+        .andReturn(false).atLeastOnce();
+
+        replay(mockListener);
+        deviceManager.addListener(mockListener);
+        verify(mockListener);
+        reset(mockListener);
+
+        ITopologyService mockTopology = createMock(ITopologyService.class);
+        expect(mockTopology.getL2DomainId(1L)).
+        andReturn(1L).anyTimes();
+        expect(mockTopology.getL2DomainId(5L)).
+        andReturn(1L).anyTimes();
+        expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())).
+        andReturn(false).anyTimes();
+        expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(),
+                                                    anyLong(), anyShort()))
+                                                    .andReturn(false).anyTimes();
+
+        expect(mockTopology.isAttachmentPointPort(anyLong(),
+                                                  anyShort())).andReturn(true).anyTimes();
+        expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)).
+        andReturn(false).anyTimes();
+
+        Date topologyUpdateTime = new Date();
+        expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime).
+        anyTimes();
+
+        replay(mockTopology);
+
+        deviceManager.topology = mockTopology;
+
+        Calendar c = Calendar.getInstance();
+        Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime());
+        c.add(Calendar.SECOND, 1);
+        Entity entity2 = new Entity(1L, null, null, 5L, 1, c.getTime());
+        c.add(Calendar.SECOND, 1);
+        Entity entity3 = new Entity(1L, null, null, 1L, 1, c.getTime());
+        c.add(Calendar.SECOND, 1);
+        Entity entity4 = new Entity(1L, null, null, 5L, 1, c.getTime());
+
+        IDevice d;
+        SwitchPort[] aps;
+
+        mockListener.deviceAdded(isA(IDevice.class));
+        replay(mockListener);
+
+        d = deviceManager.learnDeviceByEntity(entity1);
+        assertEquals(1, deviceManager.getAllDevices().size());
+        aps = d.getAttachmentPoints();
+        assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps);
+        verify(mockListener);
+
+        reset(mockListener);
+        mockListener.deviceMoved((isA(IDevice.class)));
+        replay(mockListener);
+
+        d = deviceManager.learnDeviceByEntity(entity2);
+        assertEquals(1, deviceManager.getAllDevices().size());
+        aps = d.getAttachmentPoints();
+
+        assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps);
+        verify(mockListener);
+
+        reset(mockListener);
+        mockListener.deviceMoved((isA(IDevice.class)));
+        replay(mockListener);
+
+        d = deviceManager.learnDeviceByEntity(entity3);
+        assertEquals(1, deviceManager.getAllDevices().size());
+        assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1),
+                new SwitchPort(5L, 1, ErrorStatus.DUPLICATE_DEVICE)},
+                                              d.getAttachmentPoints(true));
+        verify(mockListener);
+
+        // Generate a packet-in again from 5,1 and ensure that it doesn't
+        // create a device moved event.
+        reset(mockListener);
+        replay(mockListener);
+        d = deviceManager.learnDeviceByEntity(entity4);
+        assertEquals(1, deviceManager.getAllDevices().size());
+        assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1),
+                new SwitchPort(5L, 1, ErrorStatus.DUPLICATE_DEVICE)},
+                                              d.getAttachmentPoints(true));
+        verify(mockListener);
+    }
+
     private void verifyEntityArray(Entity[] expected, Device d) {
         Arrays.sort(expected);
         assertArrayEquals(expected, d.entities);