diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java
index 5616b2793787cf2893852e2345db2c0d790a8969..1bc258b564e0bc49084e29bfac8608d1baefbe29 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java
@@ -37,6 +37,12 @@ public interface IOFSwitchListener {
      */
     public void removedSwitch(IOFSwitch sw);
     
+    /**
+     * Fired when ports on a switch change (any change to the collection
+     * of OFPhysicalPorts and/or to a particular port)
+     */
+    public void switchPortChanged(Long switchId);
+    
     /**
      * The name assigned to this listener
      * @return
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 628ee15b969f84be23b58e463afd9e55c1906f25..9eacefcc422f8847b81b9e88ad743c45d2acdcc8 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -238,27 +238,39 @@ public class Controller implements IFloodlightProviderService,
          */
         public void dispatch();
     }
+    public enum SwitchUpdateType {
+        ADDED,
+        REMOVED,
+        PORTCHANGED
+    }
     /**
      * Update message indicating a switch was added or removed 
      */
     protected class SwitchUpdate implements IUpdate {
         public IOFSwitch sw;
-        public boolean added;
-        public SwitchUpdate(IOFSwitch sw, boolean added) {
+        public SwitchUpdateType switchUpdateType;
+        public SwitchUpdate(IOFSwitch sw, SwitchUpdateType switchUpdateType) {
             this.sw = sw;
-            this.added = added;
+            this.switchUpdateType = switchUpdateType;
         }
         public void dispatch() {
             if (log.isTraceEnabled()) {
                 log.trace("Dispatching switch update {} {}",
-                        sw, added);
+                        sw, switchUpdateType);
             }
             if (switchListeners != null) {
                 for (IOFSwitchListener listener : switchListeners) {
-                    if (added)
-                        listener.addedSwitch(sw);
-                    else
-                        listener.removedSwitch(sw);
+                    switch(switchUpdateType) {
+                        case ADDED:
+                            listener.addedSwitch(sw);
+                            break;
+                        case REMOVED:
+                            listener.removedSwitch(sw);
+                            break;
+                        case PORTCHANGED:
+                            listener.switchPortChanged(sw.getId());
+                            break;
+                    }
                 }
             }
         }
@@ -1058,6 +1070,12 @@ public class Controller implements IFloodlightProviderService,
                 removePortInfo(sw, portNumber);
             log.debug("Port #{} deleted for {}", portNumber, sw);
         }
+        SwitchUpdate update = new SwitchUpdate(sw, SwitchUpdateType.PORTCHANGED);
+        try {
+            this.updates.put(update);
+        } catch (InterruptedException e) {
+            log.error("Failure adding update to queue", e);
+        }
     }
     
     /**
@@ -1286,7 +1304,7 @@ public class Controller implements IFloodlightProviderService,
         }
         
         updateActiveSwitchInfo(sw);
-        SwitchUpdate update = new SwitchUpdate(sw, true);
+        SwitchUpdate update = new SwitchUpdate(sw, SwitchUpdateType.ADDED);
         try {
             this.updates.put(update);
         } catch (InterruptedException e) {
@@ -1325,7 +1343,7 @@ public class Controller implements IFloodlightProviderService,
         // of the switch state that's written to storage.
         
         updateInactiveSwitchInfo(sw);
-        SwitchUpdate update = new SwitchUpdate(sw, false);
+        SwitchUpdate update = new SwitchUpdate(sw, SwitchUpdateType.REMOVED);
         try {
             this.updates.put(update);
         } catch (InterruptedException e) {
@@ -1686,10 +1704,12 @@ public class Controller implements IFloodlightProviderService,
                 // ignore
             }
         }
-
-        //for (Short portNum : oldports.keySet()) {
-        //    sw.deletePort(portNum);
-        //}
+        SwitchUpdate update = new SwitchUpdate(sw, SwitchUpdateType.PORTCHANGED);
+        try {
+            this.updates.put(update);
+        } catch (InterruptedException e) {
+            log.error("Failure adding update to queue", e);
+        }
     }
     
     protected void removePortInfo(IOFSwitch sw, short portNumber) {
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
index 47b830a7a8b6e6716b6eed607deceb49f8f42ea9..17ca25979d5f419cb79dcbf08bba5a4ef0e979eb 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
@@ -1107,6 +1107,16 @@ IFloodlightModule, IInfoProvider, IHAListener {
             lock.writeLock().unlock();
         }
     }
+    
+    /**
+     * We don't react the port changed notifications here. we listen for 
+     * OFPortStatus messages directly. Might consider using this notifier
+     * instead
+     */
+    @Override
+    public void switchPortChanged(Long switchId) {
+        // no-op
+    }
 
     /** 
      * Delete links incident on a given switch port.
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
index 524757f181bf79333b91029c3d404cc0b17c6f23..e11d2d65b70036c1af0d7536c7b94627c7479f7d 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
@@ -320,6 +320,11 @@ public class StaticFlowEntryPusher
         // do NOT delete from our internal state; we're tracking the rules,
         // not the switches
     }
+    
+    @Override
+    public void switchPortChanged(Long switchId) {
+        // no-op
+    }
 
     /**
      * This handles both rowInsert() and rowUpdate()
diff --git a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
index 6e897cafd2b5f072157b10a1f44be1a549a02108..da47f272bf2236862c84e6a2b51df11c98b2001f 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
@@ -41,6 +41,9 @@ import net.floodlightcontroller.core.IListener.Command;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IOFSwitchListener;
 import net.floodlightcontroller.core.OFMessageFilterManager;
+import net.floodlightcontroller.core.internal.Controller.IUpdate;
+import net.floodlightcontroller.core.internal.Controller.SwitchUpdate;
+import net.floodlightcontroller.core.internal.Controller.SwitchUpdateType;
 import net.floodlightcontroller.core.internal.OFChannelState.HandshakeState;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.test.MockFloodlightProvider;
@@ -72,9 +75,11 @@ import org.openflow.protocol.OFPacketIn;
 import org.openflow.protocol.OFPacketOut;
 import org.openflow.protocol.OFPhysicalPort;
 import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFPortStatus;
 import org.openflow.protocol.OFStatisticsReply;
 import org.openflow.protocol.OFType;
 import org.openflow.protocol.OFPacketIn.OFPacketInReason;
+import org.openflow.protocol.OFPortStatus.OFPortReason;
 import org.openflow.protocol.OFVendor;
 import org.openflow.protocol.action.OFAction;
 import org.openflow.protocol.action.OFActionOutput;
@@ -518,9 +523,11 @@ public class ControllerTest extends FloodlightTestCase {
         class DummySwitchListener implements IOFSwitchListener {
             public int nAdded;
             public int nRemoved;
+            public int nPortChanged;
             public DummySwitchListener() {
                 nAdded = 0;
                 nRemoved = 0;
+                nPortChanged = 0;
             }
             public synchronized void addedSwitch(IOFSwitch sw) {
                 nAdded++;
@@ -533,6 +540,11 @@ public class ControllerTest extends FloodlightTestCase {
             public String getName() {
                 return "dummy";
             }
+            @Override
+            public void switchPortChanged(Long switchId) {
+                nPortChanged++;
+                notifyAll();
+            }
         }
         DummySwitchListener switchListener = new DummySwitchListener();
         IOFSwitch sw = createMock(IOFSwitch.class);
@@ -541,14 +553,21 @@ public class ControllerTest extends FloodlightTestCase {
         
         controller.addOFSwitchListener(switchListener);
         synchronized(switchListener) {
-            controller.updates.put(controller.new SwitchUpdate(sw, true));
+            controller.updates.put(controller.new SwitchUpdate(sw,
+                                      Controller.SwitchUpdateType.ADDED));
             switchListener.wait(500);
             assertTrue("IOFSwitchListener.addedSwitch() was not called", 
                     switchListener.nAdded == 1);
-            controller.updates.put(controller.new SwitchUpdate(sw, false));
+            controller.updates.put(controller.new SwitchUpdate(sw, 
+                                      Controller.SwitchUpdateType.REMOVED));
             switchListener.wait(500);
             assertTrue("IOFSwitchListener.removedSwitch() was not called", 
                     switchListener.nRemoved == 1);
+            controller.updates.put(controller.new SwitchUpdate(sw, 
+                                      Controller.SwitchUpdateType.PORTCHANGED));
+            switchListener.wait(500);
+            assertTrue("IOFSwitchListener.switchPortChanged() was not called", 
+                    switchListener.nPortChanged == 1);
         }
     }
     
@@ -1176,4 +1195,55 @@ public class ControllerTest extends FloodlightTestCase {
         assertTrue(exceptionThrown);
         verify(sw);
     }
+    
+    public void verifyPortChangedUpdateInQueue(IOFSwitch sw) throws Exception {
+        assertEquals(1, controller.updates.size());
+        IUpdate update = controller.updates.take();
+        assertEquals(true, update instanceof SwitchUpdate);
+        SwitchUpdate swUpdate = (SwitchUpdate)update;
+        assertEquals(sw, swUpdate.sw);
+        assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.switchUpdateType);
+    }
+    
+    /*
+     * Test handlePortStatus()
+     * TODO: test correct updateStorage behavior!
+     */
+    @Test 
+    public void testHandlePortStatus() throws Exception {
+        IOFSwitch sw = createMock(IOFSwitch.class);
+        OFPhysicalPort port = new OFPhysicalPort();
+        port.setName("myPortName1");
+        port.setPortNumber((short)42);
+        
+        OFPortStatus ofps = new OFPortStatus();
+        ofps.setDesc(port);
+        
+        ofps.setReason((byte)OFPortReason.OFPPR_ADD.ordinal());
+        sw.setPort(port);
+        expectLastCall().once();
+        replay(sw);
+        controller.handlePortStatusMessage(sw, ofps, false);
+        verify(sw);
+        verifyPortChangedUpdateInQueue(sw);
+        reset(sw);
+        
+        ofps.setReason((byte)OFPortReason.OFPPR_MODIFY.ordinal());
+        sw.setPort(port);
+        expectLastCall().once();
+        replay(sw);
+        controller.handlePortStatusMessage(sw, ofps, false);
+        verify(sw);
+        verifyPortChangedUpdateInQueue(sw);
+        reset(sw);
+        
+        ofps.setReason((byte)OFPortReason.OFPPR_DELETE.ordinal());
+        sw.deletePort(port.getPortNumber());
+        expectLastCall().once();
+        replay(sw);
+        controller.handlePortStatusMessage(sw, ofps, false);
+        verify(sw);
+        verifyPortChangedUpdateInQueue(sw);
+        reset(sw);
+    }
 }