diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index c3c0811f7b9ae55a971e2c106d7e48f0e2296c71..914ca9136f1a2a335757306d17aaf5cfe5e8a819 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -57,6 +57,7 @@ import net.floodlightcontroller.packet.UDP;
 import net.floodlightcontroller.routing.ForwardingBase;
 import net.floodlightcontroller.storage.IResultSet;
 import net.floodlightcontroller.storage.IStorageSource;
+import net.floodlightcontroller.storage.IStorageSourceListener;
 import net.floodlightcontroller.storage.OperatorPredicate;
 import net.floodlightcontroller.storage.StorageException;
 import net.floodlightcontroller.topology.ITopology;
@@ -85,7 +86,7 @@ import org.slf4j.LoggerFactory;
  * @author David Erickson (daviderickson@cs.stanford.edu)
  */
 public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
-        IOFSwitchListener, ITopologyAware {  
+        IOFSwitchListener, ITopologyAware, IStorageSourceListener {  
     protected static Logger log = 
         LoggerFactory.getLogger(DeviceManagerImpl.class);
 
@@ -113,6 +114,7 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
         // The Integer below is the hashCode of the device
         private Map<SwitchPortTuple, Map<Integer, Device>> switchPortDeviceMap;
         private Map<Long, List<PendingAttachmentPoint>> switchUnresolvedAPMap;
+        private Map<String, String> portChannelMap;
 
         public Map<Long, Device> getDataLayerAddressDeviceMap() {
             return dataLayerAddressDeviceMap;
@@ -146,6 +148,8 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
                 new ConcurrentHashMap<SwitchPortTuple, Map<Integer, Device>>();
             switchUnresolvedAPMap = 
                 new ConcurrentHashMap<Long, List<PendingAttachmentPoint>>();
+            portChannelMap =
+            	new ConcurrentHashMap<String, String>();
         }
 
         // ***********
@@ -385,6 +389,13 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
             return switchDeviceMap.containsKey(sw);
         }
 
+        /**
+         * Reinitialize portChannelMap upon config change
+         */
+        protected void clearPortChannelMap() {
+        	portChannelMap.clear();
+        }
+        
         // ***************************************
         // Add operations on the device attributes
         // ***************************************
@@ -534,6 +545,37 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
             }
             papl.add(pap);
         }
+        
+        /**
+         * Add switch-port to port_channel mapping to portChannelMap
+         * @param switch_id
+         * @param port_no
+         * @param port_channel
+         */
+        protected void addPortToPortChannel(String switch_id,
+        		Integer port_no, String port_channel) {
+        	String swPort = switch_id + port_no;
+        	portChannelMap.put(swPort, port_channel);
+        }
+        
+        /**
+         * Check if two ports belong to the same port channel
+         * @param swPort1
+         * @param swPort2
+         * @return
+         */
+        protected boolean inSamePortChannel(SwitchPortTuple swPort1,
+        		                            SwitchPortTuple swPort2) {
+        	String key = swPort1.getSw().getStringId() + swPort1.getPort();
+        	String portChannel1 = portChannelMap.get(swPort1.toString());
+        	if (portChannel1 == null)
+        	    return false;
+        	key = swPort2.getSw().getStringId() + swPort2.getPort();
+        	String portChannel2 = portChannelMap.get(key);
+        	if (portChannel2 == null)
+        		return false;
+        	return portChannel1.equals(portChannel2);
+        }
     } // End of DevMgrMap class definition
 
     private DevMgrMaps devMgrMaps;
@@ -545,6 +587,7 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
     protected Set<IDeviceManagerAware> deviceManagerAware;
     protected ReentrantReadWriteLock lock;
     protected volatile boolean shuttingDown = false;
+    protected volatile boolean portChannelConfigChanged = false;
 
     protected ITopology topology;
     protected LinkedList<Update> updates;
@@ -565,6 +608,8 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
                                             "controller_hostattachmentpoint";
     private static final String DEVICE_NETWORK_ADDRESS_TABLE_NAME = 
                                             "controller_hostnetworkaddress";
+    private static final String PORT_CHANNEL_TABLE_NAME = "controller_portchannel";
+    
     // Column names for the host table
     private static final String MAC_COLUMN_NAME       = "mac"; 
     private static final String VLAN_COLUMN_NAME      = "vlan"; 
@@ -578,6 +623,10 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
     private static final String AP_STATUS_COLUMN_NAME = "status";
     // Column names for the network address table
     private static final String NETWORK_ADDRESS_COLUMN_NAME = "ip";
+    // Column names for the port channel table
+    private static final String PORT_CHANNEL_COLUMN_NAME = "port_channel";
+    private static final String PC_SWITCH_COLUMN_NAME = "switch";
+    private static final String PC_PORT_COLUMN_NAME = "port";
 
     protected enum UpdateType {
         ADDED, REMOVED, MOVED, ADDRESS_ADDED, ADDRESS_REMOVED, VLAN_CHANGED
@@ -636,7 +685,8 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
         floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
         floodlightProvider.addOFMessageListener(OFType.PORT_STATUS, this);
         floodlightProvider.addOFSwitchListener(this);
-
+        storageSource.addListener(PORT_CHANNEL_TABLE_NAME, this);
+        
         /*
          * Device and storage aging.
          */
@@ -644,6 +694,7 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
 
         // Read all our device state (MACs, IPs, attachment points) from storage
         readAllDeviceStateFromStorage();
+        readPortChannelConfigFromStorage();
     }
 
     public void shutDown() {
@@ -1000,25 +1051,29 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
 
         // If curAttachmentPoint exists, we mark it a conflict and may block it.
         if (curAttachmentPoint != null) {
-            curAttachmentPoint.setConflict(currentDate);
             device.removeAttachmentPoint(curAttachmentPoint);
             device.addOldAttachmentPoint(curAttachmentPoint);
-            if (curAttachmentPoint.isFlapping()) {
-                curAttachmentPoint.setBlocked(true);
-                evHistAttachmtPt(device, curAttachmentPoint.getSwitchPort(), 
-                                        EvAction.BLOCKED, "Conflict");
-                writeAttachmentPointToStorage(device, curAttachmentPoint, 
-                                                                currentDate);
-                log.warn(
-                    "Device {}: flapping between {} and {}, block the latter",
-                    new Object[] {device, swPort, 
-                                        curAttachmentPoint.getSwitchPort()});
-            } else {
-                removeAttachmentPointFromStorage(device, curAttachmentPoint);
-                evHistAttachmtPt(device, curAttachmentPoint.getSwitchPort(), 
-                        EvAction.REMOVED, "Conflict");
+            // If two ports are in the same port-channel, we don't treat it
+            // as conflict, but will forward based on the last seen switch-port
+            if (!devMgrMaps.inSamePortChannel(swPort,
+            	    curAttachmentPoint.getSwitchPort())) {
+            	curAttachmentPoint.setConflict(currentDate);
+	        if (curAttachmentPoint.isFlapping()) {
+	            curAttachmentPoint.setBlocked(true);
+	            evHistAttachmtPt(device, curAttachmentPoint.getSwitchPort(),
+	                             EvAction.BLOCKED, "Conflict");
+	            writeAttachmentPointToStorage(device, curAttachmentPoint, 
+	                                                            currentDate);
+	            log.warn(
+	                "Device {}: flapping between {} and {}, block the latter",
+	                new Object[] {device, swPort, 
+	                              curAttachmentPoint.getSwitchPort()});
+	        } else {
+	            removeAttachmentPointFromStorage(device, curAttachmentPoint);
+                    evHistAttachmtPt(device, curAttachmentPoint.getSwitchPort(), 
+                                     EvAction.REMOVED, "Conflict");
+	        }
             }
-
             updateMoved(device, curAttachmentPoint.getSwitchPort(), 
                                                             attachmentPoint);
 
@@ -1222,6 +1277,9 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
         storageSource.createTable(DEVICE_NETWORK_ADDRESS_TABLE_NAME, null);
         storageSource.setTablePrimaryKeyName(
                         DEVICE_NETWORK_ADDRESS_TABLE_NAME, ID_COLUMN_NAME);
+        storageSource.createTable(PORT_CHANNEL_TABLE_NAME, null);
+        storageSource.setTablePrimaryKeyName(
+                        PORT_CHANNEL_TABLE_NAME, ID_COLUMN_NAME);
     }
 
     /**
@@ -1504,6 +1562,24 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
     // Storage Read Methods
     // ********************
 
+    public boolean readPortChannelConfigFromStorage() {
+    	try {
+	    	IResultSet pcResultSet = storageSource.executeQuery(
+	    			PORT_CHANNEL_TABLE_NAME, null, null, null);
+	    	
+	    	while (pcResultSet.next()) {
+	    		String port_channel = pcResultSet.getString(PORT_CHANNEL_COLUMN_NAME);
+	    		String switch_id = pcResultSet.getString(PC_SWITCH_COLUMN_NAME);
+	    		Integer port_no = pcResultSet.getInt(PC_PORT_COLUMN_NAME);
+	    		devMgrMaps.addPortToPortChannel(switch_id, port_no, port_channel);
+	    	}
+	    	return true;
+    	} catch (StorageException e) {
+    		log.error("Error reading port-channel data from storage {}", e);
+    		return false;
+    	}
+    }
+    
     public boolean readAllDeviceStateFromStorage() {
         Date currentDate = new Date();
         try {
@@ -1514,7 +1590,7 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
             return true;
         }
         catch (StorageException e) {
-            log.error("Error reading device data from storage", e);
+            log.error("Error reading device data from storage {}", e);
             return false;
         }
     }
@@ -1637,6 +1713,23 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
         // Remove the device
         storageSource.deleteRow(DEVICE_TABLE_NAME, deviceId);
     }
+    
+    /**
+     * IStorageSource listeners.
+     * Need to optimize if we support a large number of port-channel entries.
+     */
+
+    @Override
+    public void rowsModified(String tableName, Set<Object> rowKeys) {
+    	portChannelConfigChanged = true;
+        deviceUpdateTask.reschedule(5, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void rowsDeleted(String tableName, Set<Object> rowKeys) {
+    	portChannelConfigChanged = true;
+    	deviceUpdateTask.reschedule(5, TimeUnit.SECONDS);          
+    }
 
     // ********************
     // Device aging methods
@@ -1856,6 +1949,14 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
     protected class DeviceUpdateWorker implements Runnable {
         @Override
         public void run() {
+        	boolean updatePortChannel = portChannelConfigChanged;
+        	portChannelConfigChanged = false;
+        	
+        	if (updatePortChannel) {
+        		devMgrMaps.clearPortChannelMap();
+        		readPortChannelConfigFromStorage();
+        	}
+        	
             try { 
                 log.debug("DeviceUpdateWorker: cleaning up attachment points");
                 for (IOFSwitch sw  : devMgrMaps.getSwitches()) {
@@ -1871,7 +1972,7 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
                                     dCopy.getOldAttachmentPoints()) {
                                     // Don't remove conflict attachment points 
                                     // with recent activities
-                                    if (dap.isInConflict())
+                                    if (dap.isInConflict() && !updatePortChannel)
                                         continue;
                                     // Delete from memory after storage, 
                                     // otherwise an exception will