From 7e62acea5808a0de3254996bc402b92754df0637 Mon Sep 17 00:00:00 2001
From: Ryan Izard <rizard@g.clemson.edu>
Date: Thu, 31 Jul 2014 17:53:53 -0700
Subject: [PATCH] Initial OF1.3 handshake and basic Hub module working

---
 .../core/NullConnection.java                  |    2 +-
 .../core/OFConnection.java                    |    8 +-
 .../floodlightcontroller/core/OFSwitch.java   |    2 +
 .../core/internal/Controller.java             |  129 +-
 .../core/internal/ControllerCounters.java     |    6 +-
 .../core/internal/OFSwitchManager.java        | 1340 ++++++++---------
 .../core/web/CounterResource.java             |    3 +-
 .../flowcache/FlowReconcileManager.java       |   66 +-
 .../flowcache/FlowReconcileQuery.java         |   39 +-
 .../loadbalancer/LoadBalancer.java            |  327 ++--
 .../routing/ForwardingBase.java               |    2 +-
 11 files changed, 923 insertions(+), 1001 deletions(-)

diff --git a/src/main/java/net/floodlightcontroller/core/NullConnection.java b/src/main/java/net/floodlightcontroller/core/NullConnection.java
index 8ce0f55de..41a5a1591 100644
--- a/src/main/java/net/floodlightcontroller/core/NullConnection.java
+++ b/src/main/java/net/floodlightcontroller/core/NullConnection.java
@@ -34,7 +34,7 @@ public class NullConnection implements IOFConnectionBackend, IOFMessageWriter {
     }
 
     private void warn() {
-        logger.warn("Switch {} not connected -- cannot send message", getDatapathId());
+        logger.debug("Switch {} not connected -- cannot send message", getDatapathId());
     }
 
     @Override
diff --git a/src/main/java/net/floodlightcontroller/core/OFConnection.java b/src/main/java/net/floodlightcontroller/core/OFConnection.java
index ff4f529bf..58a6a1f82 100644
--- a/src/main/java/net/floodlightcontroller/core/OFConnection.java
+++ b/src/main/java/net/floodlightcontroller/core/OFConnection.java
@@ -114,13 +114,14 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{
 
     @Override
     public void write(OFMessage m) {
+    	logger.debug("Got in write() of OFConnection!!!!!");
         if (!isConnected()) {
             if (logger.isDebugEnabled())
                 logger.debug("{}: not connected - dropping message {}", this, m);
             return;
         }
-        if (logger.isTraceEnabled())
-            logger.trace("{}: send {}", this, m);
+        if (logger.isDebugEnabled())
+            logger.debug("{}: send {}", this, m);
         List<OFMessage> msgBuffer = localMsgBuffer.get();
         if (msgBuffer == null) {
             msgBuffer = new ArrayList<OFMessage>();
@@ -130,8 +131,7 @@ public class OFConnection implements IOFConnection, IOFConnectionBackend{
         counters.updateWriteStats(m);
         msgBuffer.add(m);
 
-        if ((msgBuffer.size() >= Controller.BATCH_MAX_SIZE)
-                || ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) {
+        if ((msgBuffer.size() >= Controller.BATCH_MAX_SIZE) || ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) {
             this.write(msgBuffer);
             localMsgBuffer.set(null);
         }
diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
index 410b1fea7..332f4725c 100644
--- a/src/main/java/net/floodlightcontroller/core/OFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
@@ -705,6 +705,8 @@ public class OFSwitch implements IOFSwitchBackend {
 
     @Override
     public void write(OFMessage m) {
+    	log.debug("Possible OFConnections to write to: {}", connections);
+    	log.debug("Channel info: {} {}", connections.get(OFAuxId.MAIN).getRemoteInetAddress(), connections.get(OFAuxId.MAIN).isConnected());
         connections.get(OFAuxId.MAIN).write(m);
     }
 
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 7d20f436a..c28a45e1c 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -33,7 +33,6 @@ import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
 
 import org.jboss.netty.util.HashedWheelTimer;
 import org.jboss.netty.util.Timer;
@@ -121,6 +120,12 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     protected BlockingQueue<IUpdate> updates;
     protected ControllerCounters counters;
     protected Timer timer;
+    
+    // Module Loader State
+    private ModuleLoaderState moduleLoaderState;
+    public enum ModuleLoaderState {
+        INIT, STARTUP, COMPLETE
+    }
 
     // Module dependencies
     private IStorageSourceService storageSourceService;
@@ -129,13 +134,11 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     protected IDebugEventService debugEventService;
     private IRestApiService restApiService;
     private IPktInProcessingTimeService pktinProcTimeService;
-    private IThreadPoolService threadPoolService; //TODO @Ryan is this needed here?
-    private ScheduledExecutorService scheduledExecutorService; //TODO @Ryan is this needed here?
+    private IThreadPoolService threadPoolService;
     private ISyncService syncService;
     private IShutdownService shutdownService;
     private IStoreClient<DatapathId, SwitchSyncRepresentation> storeClient;
 
-
     // Configuration options
     protected int openFlowPort = 6653; // new registered OF port number
     private String openFlowHostname = null;
@@ -143,7 +146,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     
     // The id for this controller node. Should be unique for each controller
     // node in a controller cluster.
-    protected String controllerId = "localhost";
+    protected String controllerId = "my-floodlight-controller";
 
     // This controller's current role that modules can use/query to decide
     // if they should operate in ACTIVE / STANDBY
@@ -156,15 +159,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
      * based on parameters that are only available in init()
      */
     private RoleManager roleManager;
-    // private OFSwitchManager switchManager, is implemented as a service now, IOFSwitchService
-
-    private static final int DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS =
-            15*1000; // 15s
-    private int consolidateStoreTimeDelayMs =
-            DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS;
 
     // Storage table names
-    //TODO @Ryan do we need these anymore? I think we do, since we're using StorageSource
     protected static final String CONTROLLER_TABLE_NAME = "controller_controller";
     protected static final String CONTROLLER_ID = "id";
 
@@ -198,7 +194,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     
     // Perf. related configuration
     protected static final int SEND_BUFFER_SIZE = 128 * 1024;
-    public static final int BATCH_MAX_SIZE = 100;
+    public static final int BATCH_MAX_SIZE = 1; //TODO @Ryan this was 100. Causes packet_out messages to stall until 100 accumulated...
     protected static final boolean ALWAYS_DECODE_ETH = true;
 
     // Set of port name prefixes that will be classified as uplink ports,
@@ -214,24 +210,16 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         this.uplinkPortPrefixSet = prefixSet;
     }
 
-    // Module Loader State
-    private ModuleLoaderState moduleLoaderState; //TODO move to top
-    public enum ModuleLoaderState {
-        INIT, STARTUP, COMPLETE
-    }
-
     @Override
     public ModuleLoaderState getModuleLoaderState(){
         return this.moduleLoaderState;
     }
 
     // Load monitor for overload protection
-    protected final boolean overload_drop =
-        Boolean.parseBoolean(System.getProperty("overload_drop", "false"));
+    protected final boolean overload_drop = Boolean.parseBoolean(System.getProperty("overload_drop", "false"));
     protected final LoadMonitor loadmonitor = new LoadMonitor(log);
     
-    private static class NotificationSwitchListener
-            implements IOFSwitchListener {
+    private static class NotificationSwitchListener implements IOFSwitchListener {
 
         @Override
         public void switchAdded(DatapathId switchId) {
@@ -262,13 +250,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         public void switchChanged(DatapathId switchId) {
         }
     }
-    
-    //Counters was here. Implemented as ControllerCounters in core.internal.ControllerCounters
-    
-    //RoleManager was here. Implemented as RoleManager in core.internal.RoleManager
-    
-    //SwitchManager was here. Implemented as OFSwitchManager in core.internal.OFSwitchManager
-    
+                
     /**
      *  Updates handled by the main loop
      */
@@ -279,13 +261,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         public void dispatch();
     }
     
-    //ReadyForReconcileUpdate was here. Obsolete?
-    
-    //SwitchUpdate was here. Implemented in in core.internal.OFSwitchManager
-    
-    //HARoleUpdate was here. Implemented in core.internal.RoleManager
+    //TODO @Ryan ReadyForReconcileUpdate was here. Obsolete?
     
-    //TODO @Ryan HAControllerNodeIPUpdate was here...
     /**
      * Update message indicating
      * IPs of controllers in controller cluster have changed.
@@ -486,11 +463,11 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
 
         switch (m.getType()) {
             case PACKET_IN:
+            	counters.packetIn.increment();
                 OFPacketIn pi = (OFPacketIn)m;
 
                 if (pi.getData().length <= 0) {
-                    log.error("Ignoring PacketIn (Xid = " + pi.getXid() +
-                              ") because the data field is empty.");
+                    log.error("Ignoring PacketIn (Xid = " + pi.getXid() + ") because the data field is empty.");
                     return;
                 }
 
@@ -504,8 +481,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
 
                 List<IOFMessageListener> listeners = null;
                 if (messageListeners.containsKey(m.getType())) {
-                    listeners = messageListeners.get(m.getType()).
-                            getOrderedListeners();
+                    listeners = messageListeners.get(m.getType()).getOrderedListeners();
                 }
 
                 FloodlightContext bc = null;
@@ -551,9 +527,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         }
     }
     
-    // switchActivated(IOFSwitch), switchDeactivated(IOFSwitch), switchDisconnected(IOFSwitch)
-    // removed...Included in OFSwitchManager (I'd guess... //TODO @Ryan)...
-
     // ***************
     // IFloodlightProvider
     // ***************
@@ -582,8 +555,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     }
 
     @Override
-    public synchronized void addOFMessageListener(OFType type,
-                                                  IOFMessageListener listener) {
+    public synchronized void addOFMessageListener(OFType type, IOFMessageListener listener) {
         ListenerDispatcher<OFType, IOFMessageListener> ldd =
             messageListeners.get(type);
         if (ldd == null) {
@@ -594,8 +566,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     }
 
     @Override
-    public synchronized void removeOFMessageListener(OFType type,
-                                                     IOFMessageListener listener) {
+    public synchronized void removeOFMessageListener(OFType type, IOFMessageListener listener) {
         ListenerDispatcher<OFType, IOFMessageListener> ldd =
             messageListeners.get(type);
         if (ldd != null) {
@@ -604,14 +575,9 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     }
 
     private void logListeners() {
-        for (Map.Entry<OFType,
-                       ListenerDispatcher<OFType,
-                                          IOFMessageListener>> entry
-             : messageListeners.entrySet()) {
-
+        for (Map.Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> entry : messageListeners.entrySet()) {
             OFType type = entry.getKey();
-            ListenerDispatcher<OFType, IOFMessageListener> ldd =
-                    entry.getValue();
+            ListenerDispatcher<OFType, IOFMessageListener> ldd = entry.getValue();
 
             StringBuilder sb = new StringBuilder();
             sb.append("OFListeners for ");
@@ -641,8 +607,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
     public Map<OFType, List<IOFMessageListener>> getListeners() {
         Map<OFType, List<IOFMessageListener>> lers =
             new HashMap<OFType, List<IOFMessageListener>>();
-        for(Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> e :
-            messageListeners.entrySet()) {
+        for(Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> e : messageListeners.entrySet()) {
             lers.put(e.getKey(), e.getValue().getOrderedListeners());
         }
         return Collections.unmodifiableMap(lers);
@@ -660,8 +625,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
 
         List<IOFMessageListener> listeners = null;
         if (messageListeners.containsKey(m.getType())) {
-            listeners =
-                    messageListeners.get(m.getType()).getOrderedListeners();
+            listeners = messageListeners.get(m.getType()).getOrderedListeners();
         }
 
         if (listeners != null) {
@@ -741,8 +705,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
                 recommendation=LogMessageDoc.GENERIC_ACTION)
     })
     public void run() {
-    	//TODO @Ryan, this is quite different from the bootstrap and ChannelPipelineFactory
-    	// stuff that's in the OLD_Controller class...
         this.moduleLoaderState = ModuleLoaderState.COMPLETE;
 
         if (log.isDebugEnabled()) {
@@ -769,7 +731,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         }
     }
     
-    //TODO @Ryan createServerBootStrap() was here. Implemented how/where???
+    //TODO @Ryan createServerBootStrap() was here. Implemented how/where?
 
     private void setConfigParams(Map<String, String> configParams) throws FloodlightModuleException {
         String ofPort = configParams.get("openflowPort");
@@ -788,7 +750,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
             this.workerThreads = Integer.parseInt(threads);
         }
         log.debug("Number of worker threads set to {}", this.workerThreads);
-
     }
 
     /**
@@ -800,12 +761,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
 
         // These data structures are initialized here because other
         // module's startUp() might be called before ours        
-        this.messageListeners =
-                new ConcurrentHashMap<OFType,
-                                      ListenerDispatcher<OFType,
-                                                         IOFMessageListener>>();
-        this.haListeners =
-                new ListenerDispatcher<HAListenerTypeMarker, IHAListener>();
+        this.messageListeners = new ConcurrentHashMap<OFType, ListenerDispatcher<OFType, IOFMessageListener>>();
+        this.haListeners = new ListenerDispatcher<HAListenerTypeMarker, IHAListener>();
         this.controllerNodeIPsCache = new HashMap<String, String>();
         this.updates = new LinkedBlockingQueue<IUpdate>();
         this.providerMap = new HashMap<String, List<IInfoProvider>>();
@@ -837,8 +794,7 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
                 recommendation="If this message persists, this indicates " +
                         "that the system database has failed to start. " +
                         LogMessageDoc.CHECK_CONTROLLER)
-    public void startupComponents(FloodlightModuleLoader floodlightModuleLoader)
-            throws FloodlightModuleException {
+    public void startupComponents(FloodlightModuleLoader floodlightModuleLoader) throws FloodlightModuleException {
 
         this.moduleLoaderState = ModuleLoaderState.STARTUP;
 
@@ -858,25 +814,22 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         
         // Startup load monitoring
         if (overload_drop) {
-            this.loadmonitor.startMonitoring(
-                this.threadPoolService.getScheduledExecutor());
+            this.loadmonitor.startMonitoring(this.threadPoolService.getScheduledExecutor());
         }
 
         // Add our REST API
         restApiService.addRestletRoutable(new CoreWebRoutable());
-
-        this.scheduledExecutorService = threadPoolService.getScheduledExecutor();
                 
-       /* try {
+        try {
             this.syncService.registerStore(SWITCH_SYNC_STORE_NAME, Scope.LOCAL);
-            this.storeClient = this.syncService
-                    .getStoreClient(SWITCH_SYNC_STORE_NAME,
-                                    DatapathId.class,
-                                    SwitchSyncRepresentation.class);
-            //TODO @Ryan needed? this.storeClient.addStoreListener(this.switchService);
+            this.storeClient = this.syncService.getStoreClient(
+            		SWITCH_SYNC_STORE_NAME,
+                    DatapathId.class,
+                    SwitchSyncRepresentation.class);
+            //TODO @Ryan this.storeClient.addStoreListener(this.switchService);
         } catch (SyncException e) {
             throw new FloodlightModuleException("Error while setting up sync service", e);
-        }*/
+        }
         
         addInfoProvider("summary", this);
     }
@@ -899,20 +852,17 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
                     String primary_key = (String) row.get(FLOW_COLUMN_PRIMARY_KEY);
                     if (primary_key.equals(FLOW_VALUE_PRIMARY_KEY)) {
                         if (row.containsKey(FLOW_COLUMN_ACCESS_PRIORITY)) {
-                            accessPriority =
-                                Short.valueOf((String) row.get(FLOW_COLUMN_ACCESS_PRIORITY));
+                            accessPriority = Short.valueOf((String) row.get(FLOW_COLUMN_ACCESS_PRIORITY));
                         }
                         if (row.containsKey(FLOW_COLUMN_CORE_PRIORITY)) {
-                            corePriority =
-                                    Short.valueOf((String) row.get(FLOW_COLUMN_CORE_PRIORITY));
+                            corePriority = Short.valueOf((String) row.get(FLOW_COLUMN_CORE_PRIORITY));
                         }
                     }
                 }
             }
         }
         catch (StorageException e) {
-            log.error("Failed to access storage for forwarding configuration: {}",
-                      e.getMessage());
+            log.error("Failed to access storage for forwarding configuration: {}", e.getMessage());
         }
         catch (NumberFormatException e) {
             // log error, no stack-trace
@@ -935,7 +885,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
             log.debug("Provider type {} doesn't exist.", type);
             return;
         }
-
         providerMap.get(type).remove(provider);
     }
 
@@ -947,7 +896,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         for (IInfoProvider provider : providerMap.get(type)) {
             result.putAll(provider.getInfo(type));
         }
-
         return result;
     }
 
@@ -1051,8 +999,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
         } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) {
             log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP);
         }
-
-
     }
 
     @Override
@@ -1125,7 +1071,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis
      */
     void resetModuleState() {
         this.moduleLoaderState = ModuleLoaderState.INIT;
-
     }
 
     /**
diff --git a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java
index c511a09ee..de5b99255 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java
@@ -13,12 +13,12 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 public class ControllerCounters {
 
     public final String prefix = ControllerCounters.class.getSimpleName();
-    public final String statsPrefix = IOFSwitchBackend.class.getPackage()
-                                                            .getName();
+    public final String statsPrefix = IOFSwitchBackend.class.getPackage().getName();
 
     public final IDebugCounter packetParsingError;
     public final IDebugCounter dispatchMessageWhileStandby;
     public final IDebugCounter dispatchMessage;
+    public final IDebugCounter packetIn;
 
     public ControllerCounters(IDebugCounterService debugCounters) {
         debugCounters.registerModule(prefix);
@@ -44,5 +44,7 @@ public class ControllerCounters {
                                                            "Number of times the packet parsing "
                                                                    + "encountered an error",
                                                            MetaData.ERROR);
+        
+        packetIn = debugCounters.registerCounter(prefix, "packet-in", "Number of packet_in's seen");
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
index 6e46b1cca..46d90645c 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
@@ -74,680 +74,672 @@ import com.google.common.collect.ImmutableSet;
  *
  */
 public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListener, IHAListener, IFloodlightModule, IOFSwitchService {
-    private static final Logger log = LoggerFactory.getLogger(OFSwitchManager.class);
-
-    private volatile OFControllerRole role;
-    private SwitchManagerCounters counters;
-
-    private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers;
-    private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches;
-
-    private ISwitchDriverRegistry driverRegistry;
-
-    private Set<LogicalOFMessageCategory> logicalOFMessageCategories = new CopyOnWriteArraySet<LogicalOFMessageCategory>();
-    private final List<IAppHandshakePluginFactory> handshakePlugins = new CopyOnWriteArrayList<IAppHandshakePluginFactory>();
-    private int numRequiredConnections = -1;
-    // Event IDs for debug events
-    protected IEventCategory<SwitchEvent> evSwitch;
-
-    // ISwitchService
-    protected Set<IOFSwitchListener> switchListeners;
-
-    // Module Dependencies
-    IFloodlightProviderService floodlightProvider;
-    IDebugEventService debugEventService;
-    IDebugCounterService debugCounterService;
-
-    /** IHAListener Implementation **/
-    @Override
-    public void transitionToActive() {
-        this.role = HARole.ACTIVE.getOFRole();
-    }
-
-    @Override
-    public void transitionToStandby() {
-       this.role = HARole.STANDBY.getOFRole();
-    }
-
-    /** IOFSwitchManager Implementation **/
-
-    @Override public SwitchManagerCounters getCounters() {
-        return this.counters;
-    }
-
-    private void addUpdateToQueue(IUpdate iUpdate) {
-        floodlightProvider.addUpdateToQueue(iUpdate);
-    }
-
-    @Override
-    public synchronized void switchAdded(IOFSwitchBackend sw) {
-        DatapathId dpid = sw.getId();
-        IOFSwitchBackend oldSw = this.switches.put(dpid, sw);
-        // Update event history
-        evSwitch.newEventWithFlush(new SwitchEvent(dpid, "connected"));
-
-        if (oldSw == sw)  {
-            // Note == for object equality, not .equals for value
-            counters.errorActivatedSwitchNotPresent.increment();
-            log.error("Switch {} added twice?", sw);
-            return;
-        } else if (oldSw != null) {
-            // This happens either when we have switches with duplicate
-            // DPIDs or when a switch reconnects before we saw the
-            // disconnect
-            counters.switchWithSameDpidActivated.increment();
-            log.warn("New switch added {} for already-added switch {}", sw, oldSw);
-            // We need to disconnect and remove the old switch
-            // TODO: we notify switch listeners that the switch has been
-            // removed and then we notify them that the new one has been
-            // added. One could argue that a switchChanged notification
-            // might be more appropriate in this case....
-            oldSw.cancelAllPendingRequests();
-            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED));
-            oldSw.disconnect();
-        }
-
-    }
-
-    @LogMessageDocs({
-    @LogMessageDoc(level="ERROR",
-            message="Switch {switch} activated but was already active",
-            explanation="A switch that was already activated was " +
-                        "activated again. This should not happen.",
-            recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG
-            ),
-    @LogMessageDoc(level="WARN",
-            message="New switch added {switch} for already-added switch {switch}",
-            explanation="A switch with the same DPID as another switch " +
-                    "connected to the controller.  This can be caused by " +
-                    "multiple switches configured with the same DPID, or " +
-                    "by a switch reconnected very quickly after " +
-                    "disconnecting.",
-            recommendation="If this happens repeatedly, it is likely there " +
-                    "are switches with duplicate DPIDs on the network.  " +
-                    "Reconfigure the appropriate switches.  If it happens " +
-                    "very rarely, then it is likely this is a transient " +
-                    "network problem that can be ignored."
-            )
-    })
-    @Override
-    public synchronized void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, SwitchStatus newStatus) {
-        DatapathId dpid = sw.getId();
-        IOFSwitchBackend presentSw = this.switches.get(dpid);
-
-        if (presentSw != sw)  {
-            // Note == for object equality, not .equals for value
-            counters.errorActivatedSwitchNotPresent
-                         .increment();
-            log.debug("Switch {} status change but not present in sync manager", sw);
-            return;
-        }
-        evSwitch.newEventWithFlush(new SwitchEvent(dpid,
-                                                   String.format("%s -> %s",
-                                                                 oldStatus,
-                                                                 newStatus)));
-
-        if(newStatus == SwitchStatus.MASTER  && role != OFControllerRole.ROLE_MASTER) {
-            counters.invalidSwitchActivatedWhileSlave.increment();
-            log.error("Switch {} activated but controller not MASTER", sw);
-            sw.disconnect();
-            return; // only react to switch connections when master
-        }
-
-        if(!oldStatus.isVisible() && newStatus.isVisible()) {
-            // the switch has just become visible. Send 'add' notification to our
-            // listeners
-            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED));
-        } else if((oldStatus.isVisible() && !newStatus.isVisible())) {
-            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED));
-        }
-
-        // note: no else if - both may be true
-        if(oldStatus != SwitchStatus.MASTER && newStatus == SwitchStatus.MASTER ) {
-            counters.switchActivated.increment();
-            addUpdateToQueue(new SwitchUpdate(dpid,
-                    SwitchUpdateType.ACTIVATED));
-        } else if(oldStatus == SwitchStatus.MASTER && newStatus != SwitchStatus.MASTER ) {
-            counters.switchDeactivated.increment();
-            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.DEACTIVATED));
-        }
-    }
-
-    @Override
-    public synchronized void switchDisconnected(IOFSwitchBackend sw) {
-        DatapathId dpid = sw.getId();
-        IOFSwitchBackend presentSw = this.switches.get(dpid);
-
-        if (presentSw != sw)  {
-            // Note == for object equality, not .equals for value
-            counters.errorActivatedSwitchNotPresent
-                         .increment();
-            log.warn("Switch {} disconnect but not present in sync manager", sw);
-            return;
-        }
-
-        counters.switchDisconnected.increment();
-        this.switches.remove(dpid);
-    }
-
-    @Override public void handshakeDisconnected(DatapathId dpid) {
-        this.switchHandlers.remove(dpid);
-    }
-
-    public Iterable<IOFSwitch> getActiveSwitches() {
-        ImmutableList.Builder<IOFSwitch> builder = ImmutableList.builder();
-        for(IOFSwitch sw: switches.values()) {
-            if(sw.getStatus().isControllable())
-                builder.add(sw);
-        }
-        return builder.build();
-    }
-
-    public Map<DatapathId, IOFSwitch> getAllSwitchMap(boolean showInvisible) {
-        if(showInvisible) {
-            return ImmutableMap.<DatapathId, IOFSwitch>copyOf(switches);
-        } else {
-            ImmutableMap.Builder<DatapathId, IOFSwitch> builder = ImmutableMap.builder();
-            for(IOFSwitch sw: switches.values()) {
-                if(sw.getStatus().isVisible())
-                    builder.put(sw.getId(), sw);
-            }
-            return builder.build();
-        }
-    }
-
-    @Override
-    public Map<DatapathId, IOFSwitch> getAllSwitchMap() {
-        return getAllSwitchMap(true);
-    }
-
-    @Override
-    public Set<DatapathId> getAllSwitchDpids() {
-        return getAllSwitchMap().keySet();
-    }
-
-    public Set<DatapathId> getAllSwitchDpids(boolean showInvisible) {
-        return getAllSwitchMap(showInvisible).keySet();
-    }
-
-    @Override
-    public IOFSwitch getSwitch(DatapathId dpid) {
-        return this.switches.get(dpid);
-    }
-
-    @Override
-    public IOFSwitch getActiveSwitch(DatapathId dpid) {
-        IOFSwitchBackend sw = this.switches.get(dpid);
-        if(sw != null && sw.getStatus().isVisible())
-            return sw;
-        else
-            return null;
-    }
-
-    enum SwitchUpdateType {
-        ADDED,
-        REMOVED,
-        ACTIVATED,
-        DEACTIVATED,
-        PORTCHANGED,
-        OTHERCHANGE
-    }
-
-    /**
-     * Update message indicating a switch was added or removed
-     */
-    class SwitchUpdate implements IUpdate {
-        private final DatapathId swId;
-        private final SwitchUpdateType switchUpdateType;
-        private final OFPortDesc port;
-        private final PortChangeType changeType;
-
-        public SwitchUpdate(DatapathId swId, SwitchUpdateType switchUpdateType) {
-            this(swId, switchUpdateType, null, null);
-        }
-
-        public SwitchUpdate(DatapathId swId,
-                            SwitchUpdateType switchUpdateType,
-                            OFPortDesc port,
-                            PortChangeType changeType) {
-            if (switchUpdateType == SwitchUpdateType.PORTCHANGED) {
-                if (port == null) {
-                    throw new NullPointerException("Port must not be null " +
-                            "for PORTCHANGED updates");
-                }
-                if (changeType == null) {
-                    throw new NullPointerException("ChangeType must not be " +
-                            "null for PORTCHANGED updates");
-                }
-            } else {
-                if (port != null || changeType != null) {
-                    throw new IllegalArgumentException("port and changeType " +
-                            "must be null for " + switchUpdateType +
-                            " updates");
-                }
-            }
-            this.swId = swId;
-            this.switchUpdateType = switchUpdateType;
-            this.port = port;
-            this.changeType = changeType;
-        }
-
-        @Override
-        public void dispatch() {
-            if (log.isTraceEnabled()) {
-                log.trace("Dispatching switch update {} {}", swId, switchUpdateType);
-            }
-            if (switchListeners != null) {
-                for (IOFSwitchListener listener : switchListeners) {
-                    switch(switchUpdateType) {
-                        case ADDED:
-                            // don't count here. We have more specific
-                            // counters before the update is created
-                            listener.switchAdded(swId);
-                            break;
-                        case REMOVED:
-                            // don't count here. We have more specific
-                            // counters before the update is created
-                            listener.switchRemoved(swId);
-                            break;
-                        case PORTCHANGED:
-                            counters.switchPortChanged
-                                    .increment();
-                            listener.switchPortChanged(swId, port, changeType);
-                            break;
-                        case ACTIVATED:
-                            // don't count here. We have more specific
-                            // counters before the update is created
-                            listener.switchActivated(swId);
-                            break;
-                        case DEACTIVATED:
-                            // ignore
-                            break;
-                        case OTHERCHANGE:
-                            counters.switchOtherChange
-                                    .increment();
-                            listener.switchChanged(swId);
-                            break;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Handles a new OF Connection
-     * @param IOFConnectionBackend connection an opened OF Connection
-     * @param OFFeaturesReply featuresReply the features reply received for the opened connection.
-     * It is needed for the rest of the switch handshake.
-     */
-    @Override
-    public void connectionOpened(IOFConnectionBackend connection,
-                                 OFFeaturesReply featuresReply) {
-        DatapathId dpid = connection.getDatapathId();
-        OFAuxId auxId = connection.getAuxId();
-
-        log.debug("{} opened", connection);
-
-        if(auxId.equals(OFAuxId.MAIN)) {
-
-            // Create a new switch handshake handler
-            OFSwitchHandshakeHandler handler =
-                    new OFSwitchHandshakeHandler(connection, featuresReply, this,
-                            floodlightProvider.getRoleManager(), floodlightProvider.getTimer());
-
-            OFSwitchHandshakeHandler oldHandler = switchHandlers.put(dpid, handler);
-
-            // Disconnect all the handler's connections
-            if(oldHandler != null){
-                log.debug("{} is a new main connection, killing old handler connections", connection);
-                oldHandler.cleanup();
-            }
-
-            handler.beginHandshake();
-
-        } else {
-            OFSwitchHandshakeHandler handler = switchHandlers.get(dpid);
-
-            if(handler != null) {
-                handler.auxConnectionOpened(connection);
-            }
-            // Connections have arrived before the switchhandler is ready
-            else {
-                log.warn("{} arrived before main connection, closing connection", connection);
-                connection.disconnect();
-            }
-        }
-    }
-
-    @Override
-    public void addSwitchEvent(DatapathId dpid, String reason, boolean flushNow) {
-        if (flushNow)
-            evSwitch.newEventWithFlush(new SwitchEvent(dpid, reason));
-        else
-            evSwitch.newEventNoFlush(new SwitchEvent(dpid, reason));
-    }
-
-    @Override
-    public synchronized void notifyPortChanged(IOFSwitchBackend sw,
-                           OFPortDesc port,
-                           PortChangeType changeType) {
-        Preconditions.checkNotNull(sw, "switch must not be null");
-        Preconditions.checkNotNull(port, "port must not be null");
-        Preconditions.checkNotNull(changeType, "changeType must not be null");
-
-        if (role != OFControllerRole.ROLE_MASTER) {
-            counters.invalidPortsChanged.increment();
-            return;
-        }
-        if (!this.switches.containsKey(sw.getId())) {
-            counters.invalidPortsChanged.increment();
-            return;
-        }
-
-        if(sw.getStatus().isVisible()) {
-            // no need to count here. SwitchUpdate.dispatch will count
-            // the portchanged
-            SwitchUpdate update = new SwitchUpdate(sw.getId(),
-                    SwitchUpdateType.PORTCHANGED,
-                    port, changeType);
-            addUpdateToQueue(update);
-        }
-    }
-
-    @Override
-    public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection,
-                                SwitchDescription description,
-                                OFFactory factory, DatapathId datapathId) {
-        return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId);
-    }
-
-    @Override
-    public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) {
-        floodlightProvider.handleMessage(sw, m, bContext);
-    }
-
-    @Override
-    public void addOFSwitchDriver(String manufacturerDescriptionPrefix,
-                                  IOFSwitchDriver driver) {
-        this.driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver);
-    }
-
-    @Override
-    public ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers() {
-        return ImmutableList.copyOf(this.switchHandlers.values());
-    }
-
-    @Override
-    public int getNumRequiredConnections() {
-        Preconditions.checkState(numRequiredConnections >= 0, "numRequiredConnections not calculated");
-        return numRequiredConnections;
-    }
-
-    public Set<LogicalOFMessageCategory> getLogicalOFMessageCategories() {
-        return logicalOFMessageCategories;
-    }
-
-    private int calcNumRequiredConnections() {
-        if(!this.logicalOFMessageCategories.isEmpty()){
-            // We use tree set here to maintain ordering
-            TreeSet<OFAuxId> auxConnections = new TreeSet<OFAuxId>();
-
-            for(LogicalOFMessageCategory category : this.logicalOFMessageCategories){
-                auxConnections.add(category.getAuxId());
-            }
-
-            OFAuxId first = auxConnections.first();
-            OFAuxId last = auxConnections.last();
-
-            // Check for contiguous set (1....size())
-            if(first.equals(OFAuxId.MAIN)) {
-                if(last.getValue() != auxConnections.size() - 1){
-                    throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (0,1,2,3,4,5)");
-                }
-                return auxConnections.size() - 1;
-            } else if(first.equals(OFAuxId.of(1))) {
-                if(last.getValue() != auxConnections.size()){
-                    throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (1,2,3,4,5)");
-                }
-                return auxConnections.size();
-            } else {
-                throw new IllegalStateException("Logical OF message categories must start at 0 (MAIN) or 1");
-            }
-        } else {
-            return 0;
-    }
-    }
-
-    /** ISwitchService Implementation **/
-    @Override
-    public void addOFSwitchListener(IOFSwitchListener listener) {
-        this.switchListeners.add(listener);
-    }
-
-    @Override
-    public void removeOFSwitchListener(IOFSwitchListener listener) {
-        this.switchListeners.remove(listener);
-    }
-
-    @Override
-    public void registerLogicalOFMessageCategory(LogicalOFMessageCategory category) {
-        logicalOFMessageCategories.add(category);
-    }
-
-    @Override
-    public boolean isCategoryRegistered(LogicalOFMessageCategory category) {
-        return logicalOFMessageCategories.contains(category);
-    }
-
-    @Override
-    public SwitchRepresentation getSwitchRepresentation(DatapathId dpid) {
-        IOFSwitch sw = this.switches.get(dpid);
-        OFSwitchHandshakeHandler handler = this.switchHandlers.get(dpid);
-
-        if(sw != null && handler != null) {
-            return new SwitchRepresentation(sw, handler);
-        }
-        return null;
-    }
-
-    @Override
-    public List<SwitchRepresentation> getSwitchRepresentations() {
-
-      List<SwitchRepresentation> representations = new ArrayList<SwitchRepresentation>();
-
-      for(DatapathId dpid : this.switches.keySet()) {
-          SwitchRepresentation representation = getSwitchRepresentation(dpid);
-          if(representation != null) {
-              representations.add(representation);
-          }
-      }
-      return representations;
-    }
-
-    @Override
-    public void registerHandshakePlugin(IAppHandshakePluginFactory factory) {
-        Preconditions.checkState(floodlightProvider.getModuleLoaderState() == ModuleLoaderState.INIT,
-                "handshakeplugins can only be registered when the module loader is in state INIT!");
-        handshakePlugins.add(factory);
-    }
-
-    @Override
-    public List<IAppHandshakePluginFactory> getHandshakePlugins() {
-        return handshakePlugins;
-    }
-
-    /* IFloodlightModule Implementation */
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l =
-                new ArrayList<Class<? extends IFloodlightService>>();
-            l.add(IOFSwitchService.class);
-            return l;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        Map<Class<? extends IFloodlightService>, IFloodlightService> m =
-                new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
-            m.put(IOFSwitchService.class, this);
-            return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
-
-        l.add(IFloodlightProviderService.class);
-        l.add(IDebugEventService.class);
-        l.add(IDebugCounterService.class);
-
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context) throws FloodlightModuleException {
-        // Module dependencies
-        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-        debugEventService = context.getServiceImpl(IDebugEventService.class);
-        debugCounterService = context.getServiceImpl(IDebugCounterService.class);
-
-        // Module variables
-        switchHandlers = new ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler>();
-        switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>();
-        floodlightProvider.getTimer();
-        counters = new SwitchManagerCounters(debugCounterService);
-        driverRegistry = new NaiveSwitchDriverRegistry(this);
-
-        this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>();
-
-        this.counters = new SwitchManagerCounters(debugCounterService);
-
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
-        startUpBase(context);
-        bootstrapNetty();
-    }
-
-    /**
-     * Startup method that includes everything besides the netty boostrap.
-     * This has been isolated for testing.
-     * @param context floodlight module context
-     * @throws FloodlightModuleException
-     */
-    public void startUpBase(FloodlightModuleContext context) throws FloodlightModuleException {
-        // Initial Role
-        role = floodlightProvider.getRole().getOFRole();
-
-        // IRoleListener
-        floodlightProvider.addHAListener(this);
-
-        loadLogicalCategories();
-
-        registerDebugEvents();
-    }
-
-    /**
-     * Bootstraps netty, the server that handles all openflow connections
-     */
-    public void bootstrapNetty() {
-        try {
-            final ServerBootstrap bootstrap = createServerBootStrap();
-
-             bootstrap.setOption("reuseAddr", true);
-             bootstrap.setOption("child.keepAlive", true);
-             bootstrap.setOption("child.tcpNoDelay", true);
-             bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
-
-             ChannelPipelineFactory pfact =
-                     new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService);
-             bootstrap.setPipelineFactory(pfact);
-             InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort());
-             final ChannelGroup cg = new DefaultChannelGroup();
-             cg.add(bootstrap.bind(sa));
-
-             log.info("Listening for switch connections on {}", sa);
-         } catch (Exception e) {
-             throw new RuntimeException(e);
-         }
-    }
-
-    /**
-     * Helper that bootstrapNetty.
-     * @return
-     */
-    private ServerBootstrap createServerBootStrap() {
-        if (floodlightProvider.getWorkerThreads() == 0) {
-            return new ServerBootstrap(
-                    new NioServerSocketChannelFactory(
-                            Executors.newCachedThreadPool(),
-                            Executors.newCachedThreadPool()));
-        } else {
-            return new ServerBootstrap(
-                    new NioServerSocketChannelFactory(
-                            Executors.newCachedThreadPool(),
-                            Executors.newCachedThreadPool(), floodlightProvider.getWorkerThreads()));
-        }
-    }
-
-    /**
-     * Performs startup related actions for logical OF message categories.
-     * Setting the categories list to immutable ensures that unsupported operation
-     * exceptions will be activated if modifications are attempted.
-     */
-    public void loadLogicalCategories() {
-        logicalOFMessageCategories = ImmutableSet.copyOf(logicalOFMessageCategories);
-        numRequiredConnections = calcNumRequiredConnections();
-    }
-
-    /**
-     * Registers an event handler with the debug event service
-     * for switch events.
-     * @throws FloodlightModuleException
-     */
-    private void registerDebugEvents() throws FloodlightModuleException {
-        if (debugEventService == null) {
-            debugEventService = new MockDebugEventService();
-        }
-        evSwitch = debugEventService.buildEvent(SwitchEvent.class)
-                .setModuleName(this.counters.getPrefix())
-                .setEventName("switch-event")
-                .setEventDescription("Switch connected, disconnected or port changed")
-                .setEventType(EventType.ALWAYS_LOG)
-                .setBufferCapacity(100)
-                .register();
-    }
-
-    @Override
-    public String getName() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type,
-                                            String name) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type,
-                                             String name) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-	@Override
-	public void controllerNodeIPsChanged(
-			Map<String, String> curControllerNodeIPs,
+	private static final Logger log = LoggerFactory.getLogger(OFSwitchManager.class);
+
+	private volatile OFControllerRole role;
+	private SwitchManagerCounters counters;
+
+	private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers;
+	private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches;
+
+	private ISwitchDriverRegistry driverRegistry;
+
+	private Set<LogicalOFMessageCategory> logicalOFMessageCategories = new CopyOnWriteArraySet<LogicalOFMessageCategory>();
+	private final List<IAppHandshakePluginFactory> handshakePlugins = new CopyOnWriteArrayList<IAppHandshakePluginFactory>();
+	private int numRequiredConnections = -1;
+	// Event IDs for debug events
+	protected IEventCategory<SwitchEvent> evSwitch;
+
+	// ISwitchService
+	protected Set<IOFSwitchListener> switchListeners;
+
+	// Module Dependencies
+	IFloodlightProviderService floodlightProvider;
+	IDebugEventService debugEventService;
+	IDebugCounterService debugCounterService;
+
+	/** IHAListener Implementation **/
+	@Override
+	public void transitionToActive() {
+		this.role = HARole.ACTIVE.getOFRole();
+	}
+
+	@Override
+	public void transitionToStandby() {
+		this.role = HARole.STANDBY.getOFRole();
+	}
+
+	/** IOFSwitchManager Implementation **/
+
+	@Override public SwitchManagerCounters getCounters() {
+		return this.counters;
+	}
+
+	private void addUpdateToQueue(IUpdate iUpdate) {
+		floodlightProvider.addUpdateToQueue(iUpdate);
+	}
+
+	@Override
+	public synchronized void switchAdded(IOFSwitchBackend sw) {
+		DatapathId dpid = sw.getId();
+		IOFSwitchBackend oldSw = this.switches.put(dpid, sw);
+		// Update event history
+		evSwitch.newEventWithFlush(new SwitchEvent(dpid, "connected"));
+
+		if (oldSw == sw)  {
+			// Note == for object equality, not .equals for value
+			counters.errorActivatedSwitchNotPresent.increment();
+			log.error("Switch {} added twice?", sw);
+			return;
+		} else if (oldSw != null) {
+			// This happens either when we have switches with duplicate
+			// DPIDs or when a switch reconnects before we saw the
+			// disconnect
+			counters.switchWithSameDpidActivated.increment();
+			log.warn("New switch added {} for already-added switch {}", sw, oldSw);
+			// We need to disconnect and remove the old switch
+			// TODO: we notify switch listeners that the switch has been
+			// removed and then we notify them that the new one has been
+			// added. One could argue that a switchChanged notification
+			// might be more appropriate in this case....
+			oldSw.cancelAllPendingRequests();
+			addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED));
+			oldSw.disconnect();
+		}
+
+	}
+
+	@LogMessageDocs({
+		@LogMessageDoc(level="ERROR",
+				message="Switch {switch} activated but was already active",
+				explanation="A switch that was already activated was " +
+						"activated again. This should not happen.",
+						recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG
+				),
+				@LogMessageDoc(level="WARN",
+				message="New switch added {switch} for already-added switch {switch}",
+				explanation="A switch with the same DPID as another switch " +
+						"connected to the controller.  This can be caused by " +
+						"multiple switches configured with the same DPID, or " +
+						"by a switch reconnected very quickly after " +
+						"disconnecting.",
+						recommendation="If this happens repeatedly, it is likely there " +
+								"are switches with duplicate DPIDs on the network.  " +
+								"Reconfigure the appropriate switches.  If it happens " +
+								"very rarely, then it is likely this is a transient " +
+								"network problem that can be ignored."
+						)
+	})
+	@Override
+	public synchronized void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, SwitchStatus newStatus) {
+		DatapathId dpid = sw.getId();
+		IOFSwitchBackend presentSw = this.switches.get(dpid);
+
+		if (presentSw != sw)  {
+			// Note == for object equality, not .equals for value
+			counters.errorActivatedSwitchNotPresent
+			.increment();
+			log.debug("Switch {} status change but not present in sync manager", sw);
+			return;
+		}
+		evSwitch.newEventWithFlush(new SwitchEvent(dpid,
+				String.format("%s -> %s",
+						oldStatus,
+						newStatus)));
+
+		if(newStatus == SwitchStatus.MASTER  && role != OFControllerRole.ROLE_MASTER) {
+			counters.invalidSwitchActivatedWhileSlave.increment();
+			log.error("Switch {} activated but controller not MASTER", sw);
+			sw.disconnect();
+			return; // only react to switch connections when master
+		}
+
+		if(!oldStatus.isVisible() && newStatus.isVisible()) {
+			// the switch has just become visible. Send 'add' notification to our
+			// listeners
+			addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED));
+		} else if((oldStatus.isVisible() && !newStatus.isVisible())) {
+			addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED));
+		}
+
+		// note: no else if - both may be true
+		if(oldStatus != SwitchStatus.MASTER && newStatus == SwitchStatus.MASTER ) {
+			counters.switchActivated.increment();
+			addUpdateToQueue(new SwitchUpdate(dpid,
+					SwitchUpdateType.ACTIVATED));
+		} else if(oldStatus == SwitchStatus.MASTER && newStatus != SwitchStatus.MASTER ) {
+			counters.switchDeactivated.increment();
+			addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.DEACTIVATED));
+		}
+	}
+
+	@Override
+	public synchronized void switchDisconnected(IOFSwitchBackend sw) {
+		DatapathId dpid = sw.getId();
+		IOFSwitchBackend presentSw = this.switches.get(dpid);
+
+		if (presentSw != sw)  {
+			// Note == for object equality, not .equals for value
+			counters.errorActivatedSwitchNotPresent
+			.increment();
+			log.warn("Switch {} disconnect but not present in sync manager", sw);
+			return;
+		}
+
+		counters.switchDisconnected.increment();
+		this.switches.remove(dpid);
+	}
+
+	@Override public void handshakeDisconnected(DatapathId dpid) {
+		this.switchHandlers.remove(dpid);
+	}
+
+	public Iterable<IOFSwitch> getActiveSwitches() {
+		ImmutableList.Builder<IOFSwitch> builder = ImmutableList.builder();
+		for(IOFSwitch sw: switches.values()) {
+			if(sw.getStatus().isControllable())
+				builder.add(sw);
+		}
+		return builder.build();
+	}
+
+	public Map<DatapathId, IOFSwitch> getAllSwitchMap(boolean showInvisible) {
+		if(showInvisible) {
+			return ImmutableMap.<DatapathId, IOFSwitch>copyOf(switches);
+		} else {
+			ImmutableMap.Builder<DatapathId, IOFSwitch> builder = ImmutableMap.builder();
+			for(IOFSwitch sw: switches.values()) {
+				if(sw.getStatus().isVisible())
+					builder.put(sw.getId(), sw);
+			}
+			return builder.build();
+		}
+	}
+
+	@Override
+	public Map<DatapathId, IOFSwitch> getAllSwitchMap() {
+		return getAllSwitchMap(true);
+	}
+
+	@Override
+	public Set<DatapathId> getAllSwitchDpids() {
+		return getAllSwitchMap().keySet();
+	}
+
+	public Set<DatapathId> getAllSwitchDpids(boolean showInvisible) {
+		return getAllSwitchMap(showInvisible).keySet();
+	}
+
+	@Override
+	public IOFSwitch getSwitch(DatapathId dpid) {
+		return this.switches.get(dpid);
+	}
+
+	@Override
+	public IOFSwitch getActiveSwitch(DatapathId dpid) {
+		IOFSwitchBackend sw = this.switches.get(dpid);
+		if(sw != null && sw.getStatus().isVisible())
+			return sw;
+		else
+			return null;
+	}
+
+	enum SwitchUpdateType {
+		ADDED,
+		REMOVED,
+		ACTIVATED,
+		DEACTIVATED,
+		PORTCHANGED,
+		OTHERCHANGE
+	}
+
+	/**
+	 * Update message indicating a switch was added or removed
+	 */
+	class SwitchUpdate implements IUpdate {
+		private final DatapathId swId;
+		private final SwitchUpdateType switchUpdateType;
+		private final OFPortDesc port;
+		private final PortChangeType changeType;
+
+		public SwitchUpdate(DatapathId swId, SwitchUpdateType switchUpdateType) {
+			this(swId, switchUpdateType, null, null);
+		}
+
+		public SwitchUpdate(DatapathId swId,
+				SwitchUpdateType switchUpdateType,
+				OFPortDesc port,
+				PortChangeType changeType) {
+			if (switchUpdateType == SwitchUpdateType.PORTCHANGED) {
+				if (port == null) {
+					throw new NullPointerException("Port must not be null " +
+							"for PORTCHANGED updates");
+				}
+				if (changeType == null) {
+					throw new NullPointerException("ChangeType must not be " +
+							"null for PORTCHANGED updates");
+				}
+			} else {
+				if (port != null || changeType != null) {
+					throw new IllegalArgumentException("port and changeType " +
+							"must be null for " + switchUpdateType +
+							" updates");
+				}
+			}
+			this.swId = swId;
+			this.switchUpdateType = switchUpdateType;
+			this.port = port;
+			this.changeType = changeType;
+		}
+
+		@Override
+		public void dispatch() {
+			if (log.isTraceEnabled()) {
+				log.trace("Dispatching switch update {} {}", swId, switchUpdateType);
+			}
+			if (switchListeners != null) {
+				for (IOFSwitchListener listener : switchListeners) {
+					switch(switchUpdateType) {
+					case ADDED:
+						// don't count here. We have more specific
+						// counters before the update is created
+						listener.switchAdded(swId);
+						break;
+					case REMOVED:
+						// don't count here. We have more specific
+						// counters before the update is created
+						listener.switchRemoved(swId);
+						break;
+					case PORTCHANGED:
+						counters.switchPortChanged
+						.increment();
+						listener.switchPortChanged(swId, port, changeType);
+						break;
+					case ACTIVATED:
+						// don't count here. We have more specific
+						// counters before the update is created
+						listener.switchActivated(swId);
+						break;
+					case DEACTIVATED:
+						// ignore
+						break;
+					case OTHERCHANGE:
+						counters.switchOtherChange
+						.increment();
+						listener.switchChanged(swId);
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Handles a new OF Connection
+	 * @param IOFConnectionBackend connection an opened OF Connection
+	 * @param OFFeaturesReply featuresReply the features reply received for the opened connection.
+	 * It is needed for the rest of the switch handshake.
+	 */
+	@Override
+	public void connectionOpened(IOFConnectionBackend connection,
+			OFFeaturesReply featuresReply) {
+		DatapathId dpid = connection.getDatapathId();
+		OFAuxId auxId = connection.getAuxId();
+
+		log.debug("{} opened", connection);
+
+		if(auxId.equals(OFAuxId.MAIN)) {
+
+			// Create a new switch handshake handler
+			OFSwitchHandshakeHandler handler =
+					new OFSwitchHandshakeHandler(connection, featuresReply, this,
+							floodlightProvider.getRoleManager(), floodlightProvider.getTimer());
+
+			OFSwitchHandshakeHandler oldHandler = switchHandlers.put(dpid, handler);
+
+			// Disconnect all the handler's connections
+			if(oldHandler != null){
+				log.debug("{} is a new main connection, killing old handler connections", connection);
+				oldHandler.cleanup();
+			}
+
+			handler.beginHandshake();
+
+		} else {
+			OFSwitchHandshakeHandler handler = switchHandlers.get(dpid);
+
+			if(handler != null) {
+				handler.auxConnectionOpened(connection);
+			}
+			// Connections have arrived before the switchhandler is ready
+			else {
+				log.warn("{} arrived before main connection, closing connection", connection);
+				connection.disconnect();
+			}
+		}
+	}
+
+	@Override
+	public void addSwitchEvent(DatapathId dpid, String reason, boolean flushNow) {
+		if (flushNow)
+			evSwitch.newEventWithFlush(new SwitchEvent(dpid, reason));
+		else
+			evSwitch.newEventNoFlush(new SwitchEvent(dpid, reason));
+	}
+
+	@Override
+	public synchronized void notifyPortChanged(IOFSwitchBackend sw,
+			OFPortDesc port,
+			PortChangeType changeType) {
+		Preconditions.checkNotNull(sw, "switch must not be null");
+		Preconditions.checkNotNull(port, "port must not be null");
+		Preconditions.checkNotNull(changeType, "changeType must not be null");
+
+		if (role != OFControllerRole.ROLE_MASTER) {
+			counters.invalidPortsChanged.increment();
+			return;
+		}
+		if (!this.switches.containsKey(sw.getId())) {
+			counters.invalidPortsChanged.increment();
+			return;
+		}
+
+		if(sw.getStatus().isVisible()) {
+			// no need to count here. SwitchUpdate.dispatch will count
+			// the portchanged
+			SwitchUpdate update = new SwitchUpdate(sw.getId(),
+					SwitchUpdateType.PORTCHANGED,
+					port, changeType);
+			addUpdateToQueue(update);
+		}
+	}
+
+	@Override
+	public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection,
+			SwitchDescription description,
+			OFFactory factory, DatapathId datapathId) {
+		return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId);
+	}
+
+	@Override
+	public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) {
+		floodlightProvider.handleMessage(sw, m, bContext);
+	}
+
+	@Override
+	public void addOFSwitchDriver(String manufacturerDescriptionPrefix,
+			IOFSwitchDriver driver) {
+		this.driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver);
+	}
+
+	@Override
+	public ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers() {
+		return ImmutableList.copyOf(this.switchHandlers.values());
+	}
+
+	@Override
+	public int getNumRequiredConnections() {
+		Preconditions.checkState(numRequiredConnections >= 0, "numRequiredConnections not calculated");
+		return numRequiredConnections;
+	}
+
+	public Set<LogicalOFMessageCategory> getLogicalOFMessageCategories() {
+		return logicalOFMessageCategories;
+	}
+
+	private int calcNumRequiredConnections() {
+		if(!this.logicalOFMessageCategories.isEmpty()){
+			// We use tree set here to maintain ordering
+			TreeSet<OFAuxId> auxConnections = new TreeSet<OFAuxId>();
+
+			for(LogicalOFMessageCategory category : this.logicalOFMessageCategories){
+				auxConnections.add(category.getAuxId());
+			}
+
+			OFAuxId first = auxConnections.first();
+			OFAuxId last = auxConnections.last();
+
+			// Check for contiguous set (1....size())
+			if(first.equals(OFAuxId.MAIN)) {
+				if(last.getValue() != auxConnections.size() - 1){
+					throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (0,1,2,3,4,5)");
+				}
+				return auxConnections.size() - 1;
+			} else if(first.equals(OFAuxId.of(1))) {
+				if(last.getValue() != auxConnections.size()){
+					throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (1,2,3,4,5)");
+				}
+				return auxConnections.size();
+			} else {
+				throw new IllegalStateException("Logical OF message categories must start at 0 (MAIN) or 1");
+			}
+		} else {
+			return 0;
+		}
+	}
+
+	/** ISwitchService Implementation **/
+	@Override
+	public void addOFSwitchListener(IOFSwitchListener listener) {
+		this.switchListeners.add(listener);
+	}
+
+	@Override
+	public void removeOFSwitchListener(IOFSwitchListener listener) {
+		this.switchListeners.remove(listener);
+	}
+
+	@Override
+	public void registerLogicalOFMessageCategory(LogicalOFMessageCategory category) {
+		logicalOFMessageCategories.add(category);
+	}
+
+	@Override
+	public boolean isCategoryRegistered(LogicalOFMessageCategory category) {
+		return logicalOFMessageCategories.contains(category);
+	}
+
+	@Override
+	public SwitchRepresentation getSwitchRepresentation(DatapathId dpid) {
+		IOFSwitch sw = this.switches.get(dpid);
+		OFSwitchHandshakeHandler handler = this.switchHandlers.get(dpid);
+
+		if(sw != null && handler != null) {
+			return new SwitchRepresentation(sw, handler);
+		}
+		return null;
+	}
+
+	@Override
+	public List<SwitchRepresentation> getSwitchRepresentations() {
+
+		List<SwitchRepresentation> representations = new ArrayList<SwitchRepresentation>();
+
+		for(DatapathId dpid : this.switches.keySet()) {
+			SwitchRepresentation representation = getSwitchRepresentation(dpid);
+			if(representation != null) {
+				representations.add(representation);
+			}
+		}
+		return representations;
+	}
+
+	@Override
+	public void registerHandshakePlugin(IAppHandshakePluginFactory factory) {
+		Preconditions.checkState(floodlightProvider.getModuleLoaderState() == ModuleLoaderState.INIT,
+				"handshakeplugins can only be registered when the module loader is in state INIT!");
+		handshakePlugins.add(factory);
+	}
+
+	@Override
+	public List<IAppHandshakePluginFactory> getHandshakePlugins() {
+		return handshakePlugins;
+	}
+
+	/* IFloodlightModule Implementation */
+	@Override
+	public Collection<Class<? extends IFloodlightService>>
+	getModuleServices() {
+		Collection<Class<? extends IFloodlightService>> l =
+				new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IOFSwitchService.class);
+		return l;
+	}
+
+	@Override
+	public Map<Class<? extends IFloodlightService>, IFloodlightService>
+	getServiceImpls() {
+		Map<Class<? extends IFloodlightService>, IFloodlightService> m =
+				new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+		m.put(IOFSwitchService.class, this);
+		return m;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>>
+	getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+
+		l.add(IFloodlightProviderService.class);
+		l.add(IDebugEventService.class);
+		l.add(IDebugCounterService.class);
+
+		return l;
+	}
+
+	@Override
+	public void init(FloodlightModuleContext context) throws FloodlightModuleException {
+		// Module dependencies
+		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+		debugEventService = context.getServiceImpl(IDebugEventService.class);
+		debugCounterService = context.getServiceImpl(IDebugCounterService.class);
+
+		// Module variables
+		switchHandlers = new ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler>();
+		switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>();
+		floodlightProvider.getTimer();
+		counters = new SwitchManagerCounters(debugCounterService);
+		driverRegistry = new NaiveSwitchDriverRegistry(this);
+
+		this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>();
+
+		this.counters = new SwitchManagerCounters(debugCounterService);
+
+	}
+
+	@Override
+	public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
+		startUpBase(context);
+		bootstrapNetty();
+	}
+
+	/**
+	 * Startup method that includes everything besides the netty boostrap.
+	 * This has been isolated for testing.
+	 * @param context floodlight module context
+	 * @throws FloodlightModuleException
+	 */
+	public void startUpBase(FloodlightModuleContext context) throws FloodlightModuleException {
+		// Initial Role
+		role = floodlightProvider.getRole().getOFRole();
+
+		// IRoleListener
+		floodlightProvider.addHAListener(this);
+
+		loadLogicalCategories();
+
+		registerDebugEvents();
+	}
+
+	/**
+	 * Bootstraps netty, the server that handles all openflow connections
+	 */
+	public void bootstrapNetty() {
+		try {
+			final ServerBootstrap bootstrap = createServerBootStrap();
+
+			bootstrap.setOption("reuseAddr", true);
+			bootstrap.setOption("child.keepAlive", true);
+			bootstrap.setOption("child.tcpNoDelay", true);
+			bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
+
+			ChannelPipelineFactory pfact =
+					new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService);
+			bootstrap.setPipelineFactory(pfact);
+			InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort());
+			final ChannelGroup cg = new DefaultChannelGroup();
+			cg.add(bootstrap.bind(sa));
+
+			log.info("Listening for switch connections on {}", sa);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * Helper that bootstrapNetty.
+	 * @return
+	 */
+	private ServerBootstrap createServerBootStrap() {
+		if (floodlightProvider.getWorkerThreads() == 0) {
+			return new ServerBootstrap(
+					new NioServerSocketChannelFactory(
+							Executors.newCachedThreadPool(),
+							Executors.newCachedThreadPool()));
+		} else {
+			return new ServerBootstrap(
+					new NioServerSocketChannelFactory(
+							Executors.newCachedThreadPool(),
+							Executors.newCachedThreadPool(), floodlightProvider.getWorkerThreads()));
+		}
+	}
+
+	/**
+	 * Performs startup related actions for logical OF message categories.
+	 * Setting the categories list to immutable ensures that unsupported operation
+	 * exceptions will be activated if modifications are attempted.
+	 */
+	public void loadLogicalCategories() {
+		logicalOFMessageCategories = ImmutableSet.copyOf(logicalOFMessageCategories);
+		numRequiredConnections = calcNumRequiredConnections();
+	}
+
+	/**
+	 * Registers an event handler with the debug event service
+	 * for switch events.
+	 * @throws FloodlightModuleException
+	 */
+	private void registerDebugEvents() throws FloodlightModuleException {
+		if (debugEventService == null) {
+			debugEventService = new MockDebugEventService();
+		}
+		evSwitch = debugEventService.buildEvent(SwitchEvent.class)
+				.setModuleName(this.counters.getPrefix())
+				.setEventName("switch-event")
+				.setEventDescription("Switch connected, disconnected or port changed")
+				.setEventType(EventType.ALWAYS_LOG)
+				.setBufferCapacity(100)
+				.register();
+	}
+
+	@Override
+	public String getName() {
+		return null;
+	}
+
+	@Override
+	public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type, String name) {
+		return false;
+	}
+
+	@Override
+	public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type, String name) {
+		return false;
+	}
+
+	@Override
+	public void controllerNodeIPsChanged(Map<String, String> curControllerNodeIPs,
 			Map<String, String> addedControllerNodeIPs,
-			Map<String, String> removedControllerNodeIPs) {
-		// TODO Auto-generated method stub
-		
+			Map<String, String> removedControllerNodeIPs) {		
 	}
 }
diff --git a/src/main/java/net/floodlightcontroller/core/web/CounterResource.java b/src/main/java/net/floodlightcontroller/core/web/CounterResource.java
index 35c771c2c..14fa1b1e3 100644
--- a/src/main/java/net/floodlightcontroller/core/web/CounterResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/CounterResource.java
@@ -47,7 +47,8 @@ public class CounterResource extends CounterResourceBase {
                 }   
             }   
         } else {
-            List<DebugCounterResource> counter = this.debugCounterService.getCounterHierarchy(moduleName, counterTitle);
+            List<DebugCounterResource> counter = this.debugCounterService.getCounterHierarchy(???, counterTitle));
+            long v = 0;
             if (counter != null) {
                 v = counter.getCounterValue();
             } else {
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java
index 4c517a25b..f5fedabdf 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java
@@ -26,12 +26,14 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.ListenerDispatcher;
 import net.floodlightcontroller.core.util.SingletonTask;
+import net.floodlightcontroller.debugcounter.DebugCounterResource;
 import net.floodlightcontroller.debugcounter.IDebugCounter;
 import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.flowcache.FlowReconcileQuery.FlowReconcileQueryDebugEvent;
@@ -44,24 +46,24 @@ import org.projectfloodlight.openflow.protocol.OFType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class FlowReconcileManager
-        implements IFloodlightModule, IFlowReconcileService {
+import com.sun.j3d.utils.scenegraph.io.retained.Controller;
 
+public class FlowReconcileManager implements IFloodlightModule, IFlowReconcileService {
     /** The logger. */
-    private static Logger logger =
-                        LoggerFactory.getLogger(FlowReconcileManager.class);
+    private static Logger logger =  LoggerFactory.getLogger(FlowReconcileManager.class);
 
     /** Reference to dependent modules */
-    protected IThreadPoolService threadPool;
+    protected IThreadPoolService threadPoolService;
     protected IDebugCounterService debugCounterService;
+    protected IFloodlightProviderService floodlightProviderService;
+    
     /**
      * The list of flow reconcile listeners that have registered to get
      * flow reconcile callbacks. Such callbacks are invoked, for example, when
      * a switch with existing flow-mods joins this controller and those flows
      * need to be reconciled with the current configuration of the controller.
      */
-    protected ListenerDispatcher<OFType, IFlowReconcileListener>
-                                               flowReconcileListeners;
+    protected ListenerDispatcher<OFType, IFlowReconcileListener> flowReconcileListeners;
 
     /** A FIFO queue to keep all outstanding flows for reconciliation */
     PriorityPendingQueue <OFMatchReconcile> flowQueue;
@@ -69,7 +71,7 @@ public class FlowReconcileManager
     /** Asynchronous task to feed the flowReconcile pipeline */
     protected SingletonTask flowReconcileTask;
 
-    String controllerPktInCounterName;
+    protected DebugCounterResource ctrControllerPktIn;
     protected IDebugCounter lastPacketInCounter;
 
     protected final static int MAX_SYSTEM_LOAD_PER_SECOND = 10000;
@@ -91,6 +93,7 @@ public class FlowReconcileManager
     private IDebugCounter ctrFlowReconcileRequest;
     private IDebugCounter ctrReconciledFlows;
     protected boolean flowReconcileEnabled;
+    private DebugCounterResource ctrPacketInRsrc = null;
 
     public AtomicInteger flowReconcileThreadRunCount;
 
@@ -191,11 +194,11 @@ public class FlowReconcileManager
     @Override
     public void init(FloodlightModuleContext context)
             throws FloodlightModuleException {
-        threadPool = context.getServiceImpl(IThreadPoolService.class);
+    	floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
+        threadPoolService = context.getServiceImpl(IThreadPoolService.class);
         debugCounterService = context.getServiceImpl(IDebugCounterService.class);
         flowQueue = new PriorityPendingQueue<OFMatchReconcile>();
-        flowReconcileListeners =
-                new ListenerDispatcher<OFType, IFlowReconcileListener>();
+        flowReconcileListeners = new ListenerDispatcher<OFType, IFlowReconcileListener>();
 
         Map<String, String> configParam = context.getConfigParams(this);
         String enableValue = configParam.get(EnableConfigKey);
@@ -216,6 +219,7 @@ public class FlowReconcileManager
             logger.error("Debug Counter Service not found.");
         }
         try {
+        	debugCounterService.registerModule(PACKAGE);
             ctrFlowReconcileRequest = debugCounterService.registerCounter(PACKAGE, "flow-reconcile-request",
                 "All flow reconcile request received by this module");
             ctrReconciledFlows = debugCounterService.registerCounter(PACKAGE, "reconciled-flows",
@@ -229,7 +233,7 @@ public class FlowReconcileManager
     @Override
     public void startUp(FloodlightModuleContext context) {
         // thread to do flow reconcile
-        ScheduledExecutorService ses = threadPool.getScheduledExecutor();
+        ScheduledExecutorService ses = threadPoolService.getScheduledExecutor();
         flowReconcileTask = new SingletonTask(ses, new Runnable() {
             @Override
             public void run() {
@@ -247,11 +251,6 @@ public class FlowReconcileManager
 
         String packetInName = OFType.PACKET_IN.getClass().getName();
         packetInName = packetInName.substring(packetInName.lastIndexOf('.')+1);
-
-        // Construct controller counter for the packet_in
-        /*controllerPktInCounterName = debugCounterService. CounterStore.createCounterName(ICounterStoreService.CONTROLLER_NAME,
-                                           -1,
-                                           packetInName); */
     }
 
     protected void updateFlush() {
@@ -319,7 +318,7 @@ public class FlowReconcileManager
             for (OFMatchReconcile ofmRc : ofmRcList) {
                 if (ofmRc.origReconcileQueryEvent != null) {
                     ofmRc.origReconcileQueryEvent.evType.getDebugEvent()
-                        .updateEventWithFlush(new FlowReconcileQueryDebugEvent(
+                    .newEventWithFlush(new FlowReconcileQueryDebugEvent(
                             ofmRc.origReconcileQueryEvent,
                             "Flow Reconciliation Complete",
                             ofmRc));
@@ -363,26 +362,25 @@ public class FlowReconcileManager
      * @return
      */
     protected int getCurrentCapacity() {
-        IDebugCounter pktInCounter =
-            counterStore.getCounter(controllerPktInCounterName);
-        int minFlows = MIN_FLOW_RECONCILE_PER_SECOND *
-                        FLOW_RECONCILE_DELAY_MILLISEC / 1000;
-
+        int minFlows = MIN_FLOW_RECONCILE_PER_SECOND * FLOW_RECONCILE_DELAY_MILLISEC / 1000;
+        
+        List<DebugCounterResource> contCtrRsrcList = debugCounterService.getModuleCounterValues(Controller.class.getName());
+        for (DebugCounterResource dcr : contCtrRsrcList) {
+        	if (dcr.getCounterHierarchy().equals("packet-in")) {
+                ctrPacketInRsrc = dcr;
+                break;
+        	}
+        }
+        
         // If no packetInCounter, then there shouldn't be any flow.
-        if (pktInCounter == null ||
-            pktInCounter.getCounterDate() == null ||
-            pktInCounter.getCounterValue() == null) {
-            logger.debug("counter {} doesn't exist",
-                        controllerPktInCounterName);
+        if (ctrPacketInRsrc == null || ctrPacketInRsrc.getCounterValue() == null || ctrPacketInRsrc.getCounterValue() == 0) {
+            logger.debug("counter {} doesn't exist", ctrPacketInRsrc);
             return minFlows;
         }
 
-        // Haven't get any counter yet.
-        if (lastPacketInCounter == null) {
-            logger.debug("First time get the count for {}",
-                        controllerPktInCounterName);
-            lastPacketInCounter = (SimpleCounter)
-            SimpleCounter.createCounter(pktInCounter);
+        // We're the first packet_in
+        if (lastPacketInCounter.getCounterValue() == 0) {
+            logger.debug("First time get the count for {}", lastPacketInCounter);
             return minFlows;
         }
 
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java
index 68a433ef7..538e01d87 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileQuery.java
@@ -21,8 +21,9 @@ import java.lang.ref.SoftReference;
 import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
 import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType;
 import net.floodlightcontroller.debugevent.IDebugEventService.EventType;
+import net.floodlightcontroller.debugevent.IEventCategory;
 import net.floodlightcontroller.debugevent.IDebugEventService;
-import net.floodlightcontroller.debugevent.IEventUpdater;
+import net.floodlightcontroller.debugevent.MockDebugEventService;
 import net.floodlightcontroller.flowcache.PriorityPendingQueue.EventPriority;
 
 /**
@@ -92,33 +93,37 @@ public class FlowReconcileQuery {
 
         private String description;
         private EventPriority priority;
-        private IEventUpdater<FlowReconcileQueryDebugEvent>
-                evReconcileQueryDebugEvent;
+        private IEventCategory<FlowReconcileQueryDebugEvent> eventCategory;
+        private IDebugEventService debugEventService;
 
-        private ReconcileQueryEvType(EventPriority priority,
-                                     String description) {
+        private ReconcileQueryEvType(EventPriority priority, String description) {
             this.priority = priority;
             this.description = description;
         }
+        
         public EventPriority getPriority() {
              return this.priority;
         }
+        
         public String getDescription() {
             return description;
         }
-        public void registerDebugEvent(String packageName,
-                                       IDebugEventService debugEvents)
-                evReconcileQueryDebugEvent =
-                    debugEvents.registerEvent(
-                        packageName,
-                        this.toString().toLowerCase().replace("_", "-"),
-                        this.getDescription(),
-                        EventType.ALWAYS_LOG,
-                        FlowReconcileQueryDebugEvent.class,
-                        500);
+        
+        public void registerDebugEvent(String packageName, IDebugEventService debugEvents) {
+        	 if (debugEventService == null) {
+                 debugEventService = new MockDebugEventService();
+             }
+                eventCategory = debugEventService.buildEvent(FlowReconcileQueryDebugEvent.class)
+                    .setModuleName(packageName)
+                    .setEventName(this.toString().toLowerCase().replace("_", "-"))
+                    .setEventDescription(this.getDescription())
+                    .setEventType(EventType.ALWAYS_LOG)
+                    .setBufferCapacity(500)
+                    .register();
         }
-        public IEventUpdater<FlowReconcileQueryDebugEvent> getDebugEvent() {
-            return evReconcileQueryDebugEvent;
+    
+        public IEventCategory<FlowReconcileQueryDebugEvent> getDebugEvent() {
+            return eventCategory;
         }
     }
     public FlowReconcileQuery(ReconcileQueryEvType evType) {
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
index 36212b889..64c835ace 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
@@ -32,11 +32,12 @@ import java.util.regex.Pattern;
 
 import org.projectfloodlight.openflow.protocol.OFFlowMod;
 import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.OFFactories;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPacketIn;
 import org.projectfloodlight.openflow.protocol.OFPacketOut;
-import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.protocol.action.OFAction;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
@@ -50,14 +51,17 @@ import org.projectfloodlight.openflow.protocol.action.OFActionSetTpSrc;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetTpDst;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp; // PCP = Priority Code Point
-import org.projectfloodlight.openflow.util.HexString;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.IPv4Address;
 import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.MacAddress;
 import org.projectfloodlight.openflow.types.OFBufferId;
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.TransportPort;
 import org.projectfloodlight.openflow.types.U16;
+import org.projectfloodlight.openflow.types.U64;
+import org.projectfloodlight.openflow.types.VlanPcp;
+import org.projectfloodlight.openflow.types.VlanVid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,6 +69,7 @@ import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.internal.IOFSwitchService;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -87,6 +92,7 @@ import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService;
 import net.floodlightcontroller.topology.ITopologyService;
 import net.floodlightcontroller.topology.NodePortTuple;
 import net.floodlightcontroller.util.MACAddress;
+import net.floodlightcontroller.util.MatchString;
 import net.floodlightcontroller.util.OFMessageDamper;
 
 /**
@@ -108,15 +114,16 @@ public class LoadBalancer implements IFloodlightModule,
     protected static Logger log = LoggerFactory.getLogger(LoadBalancer.class);
 
     // Our dependencies
-    protected IFloodlightProviderService floodlightProvider;
-    protected IRestApiService restApi;
+    protected IFloodlightProviderService floodlightProviderService;
+    protected IRestApiService restApiService;
     
     protected IDebugCounterService debugCounterService;
     protected OFMessageDamper messageDamper;
-    protected IDeviceService deviceManager;
-    protected IRoutingService routingEngine;
-    protected ITopologyService topology;
-    protected IStaticFlowEntryPusherService sfp;
+    protected IDeviceService deviceManagerService;
+    protected IRoutingService routingEngineService;
+    protected ITopologyService topologyService;
+    protected IStaticFlowEntryPusherService sfpService;
+    protected IOFSwitchService switchService;
     
     protected HashMap<String, LBVip> vips;
     protected HashMap<String, LBPool> pools;
@@ -138,9 +145,9 @@ public class LoadBalancer implements IFloodlightModule,
                 @Override
                 public int compare(SwitchPort d1, SwitchPort d2) {
                     DatapathId d1ClusterId = 
-                            topology.getL2DomainId(d1.getSwitchDPID());
+                            topologyService.getL2DomainId(d1.getSwitchDPID());
                     DatapathId d2ClusterId = 
-                            topology.getL2DomainId(d2.getSwitchDPID());
+                            topologyService.getL2DomainId(d2.getSwitchDPID());
                     return d1ClusterId.compareTo(d2ClusterId);
                 }
             };
@@ -191,12 +198,9 @@ public class LoadBalancer implements IFloodlightModule,
         return Command.CONTINUE;
     }
 
-    private net.floodlightcontroller.core.IListener.Command
-            processPacketIn(IOFSwitch sw, OFPacketIn pi,
-                            FloodlightContext cntx) {
+    private net.floodlightcontroller.core.IListener.Command processPacketIn(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
         
-        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
-                                                              IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
         IPacket pkt = eth.getPayload();
  
         if (eth.isBroadcast() || eth.isMulticast()) {
@@ -325,9 +329,9 @@ public class LoadBalancer implements IFloodlightModule,
      */    
     public void pushPacket(IPacket packet, 
                            IOFSwitch sw,
-                           int bufferId,
-                           short inPort,
-                           short outPort, 
+                           OFBufferId bufferId,
+                           OFPort inPort,
+                           OFPort outPort, 
                            FloodlightContext cntx,
                            boolean flush) {
         if (log.isTraceEnabled()) {
@@ -335,25 +339,20 @@ public class LoadBalancer implements IFloodlightModule,
                       new Object[] {sw, inPort, outPort});
         }
 
-        OFPacketOut po =
-                (OFPacketOut) floodlightProvider.getOFMessageFactory()
-                                                .getMessage(OFType.PACKET_OUT);
+        OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
 
         // set actions
         List<OFAction> actions = new ArrayList<OFAction>();
-        actions.add(new OFActionOutput(outPort, (short) 0xffff));
-
-        po.setActions(actions)
-          .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH);
-        short poLength =
-                (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH);
+        actions.add(sw.getOFFactory().actions().buildOutput().setPort(outPort).build());
 
+        pob.setActions(actions);
+        
         // set buffer_id, in_port
-        po.setBufferId(bufferId);
-        po.setInPort(inPort);
+        pob.setBufferId(bufferId);
+        pob.setInPort(inPort);
 
         // set data - only if buffer_id == -1
-        if (po.getBufferId() == OFPacketOut.BUFFER_ID_NONE) {
+        if (pob.getBufferId() == OFBufferId.NO_BUFFER) {
             if (packet == null) {
                 log.error("BufferId is not set and packet data is null. " +
                           "Cannot send packetOut. " +
@@ -362,15 +361,12 @@ public class LoadBalancer implements IFloodlightModule,
                 return;
             }
             byte[] packetData = packet.serialize();
-            poLength += packetData.length;
-            po.setPacketData(packetData);
+            pob.setData(packetData);
         }
 
-        po.setLength(poLength);
-
         try {
-            counterStore.updatePktOutFMCounterStoreLocal(sw, po);
-            messageDamper.write(sw, po, cntx, flush);
+            //TODO @Ryan debugCounterService.updatePktOutFMCounterStoreLocal(sw, pob.build());
+            messageDamper.write(sw, pob.build(), cntx, flush);
         } catch (IOException e) {
             log.error("Failure writing packet out", e);
         }
@@ -392,8 +388,7 @@ public class LoadBalancer implements IFloodlightModule,
         IDevice dstDevice = null;
         
         // retrieve all known devices
-        Collection<? extends IDevice> allDevices = deviceManager
-                .getAllDevices();
+        Collection<? extends IDevice> allDevices = deviceManagerService.getAllDevices();
         
         for (IDevice d : allDevices) {
             for (int j = 0; j < d.getIPv4Addresses().length; j++) {
@@ -411,7 +406,7 @@ public class LoadBalancer implements IFloodlightModule,
         // srcDevice and/or dstDevice is null, no route can be pushed
         if (srcDevice == null || dstDevice == null) return;
         
-        DatapathId srcIsland = topology.getL2DomainId(sw.getId());
+        DatapathId srcIsland = topologyService.getL2DomainId(sw.getId());
 
         if (srcIsland == null) {
             log.debug("No openflow island found for source {}/{}", 
@@ -425,7 +420,7 @@ public class LoadBalancer implements IFloodlightModule,
         boolean on_same_if = false;
         for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) {
             DatapathId dstSwDpid = dstDap.getSwitchDPID();
-            DatapathId dstIsland = topology.getL2DomainId(dstSwDpid);
+            DatapathId dstIsland = topologyService.getL2DomainId(dstSwDpid);
             if ((dstIsland != null) && dstIsland.equals(srcIsland)) {
                 on_same_island = true;
                 if ((sw.getId() == dstSwDpid) &&
@@ -470,9 +465,9 @@ public class LoadBalancer implements IFloodlightModule,
             SwitchPort srcDap = srcDaps[iSrcDaps];
             SwitchPort dstDap = dstDaps[iDstDaps];
             DatapathId srcCluster = 
-                    topology.getL2DomainId(srcDap.getSwitchDPID());
+                    topologyService.getL2DomainId(srcDap.getSwitchDPID());
             DatapathId dstCluster = 
-                    topology.getL2DomainId(dstDap.getSwitchDPID());
+                    topologyService.getL2DomainId(dstDap.getSwitchDPID());
 
             int srcVsDest = srcCluster.compareTo(dstCluster);
             if (srcVsDest == 0) {
@@ -480,12 +475,12 @@ public class LoadBalancer implements IFloodlightModule,
                         (srcCluster != null) && 
                         (dstCluster != null)) {
                     Route routeIn = 
-                            routingEngine.getRoute(srcDap.getSwitchDPID(),
+                            routingEngineService.getRoute(srcDap.getSwitchDPID(),
                                                    srcDap.getPort(),
                                                    dstDap.getSwitchDPID(),
                                                    dstDap.getPort(), 0);
                     Route routeOut = 
-                            routingEngine.getRoute(dstDap.getSwitchDPID(),
+                            routingEngineService.getRoute(dstDap.getSwitchDPID(),
                                                    dstDap.getPort(),
                                                    srcDap.getSwitchDPID(),
                                                    srcDap.getPort(), 0);
@@ -533,17 +528,14 @@ public class LoadBalancer implements IFloodlightModule,
                String matchString = null;
                String actionString = null;
                
-               OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory()
-                       .getMessage(OFType.FLOW_MOD);
-
-               fm.setIdleTimeout((short) 0);   // infinite
-               fm.setHardTimeout((short) 0);   // infinite
-               fm.setBufferId(OFPacketOut.BUFFER_ID_NONE);
-               fm.setCommand((short) 0);
-               fm.setFlags((short) 0);
-               fm.setOutPort(OFPort.OFPP_NONE.getValue());
-               fm.setCookie((long) 0);  
-               fm.setPriority(Short.MAX_VALUE);
+               OFFlowMod.Builder fmb = switchService.getSwitch(pinSwitch).getOFFactory().buildFlowModify();
+
+               fmb.setIdleTimeout((short) 0);   // infinite
+               fmb.setHardTimeout((short) 0);   // infinite
+               fmb.setBufferId(OFBufferId.NO_BUFFER);
+               fmb.setOutPort(OFPort.ANY); //TODO @Ryan is this the same as OFPort.NONE in the old openflowj?
+               fmb.setCookie(U64.of(0));  
+               fmb.setPriority(Short.MAX_VALUE);
                
                if (inBound) {
                    entryName = "inbound-vip-"+ member.vipId+"-client-"+client.ipAddress+"-port-"+client.targetPort
@@ -581,20 +573,19 @@ public class LoadBalancer implements IFloodlightModule,
                    
                }
                
-               parseActionString(fm, actionString, log);
+               parseActionString(fmb.build(), actionString, log);
 
-               fm.setPriority(U16.t(LB_PRIORITY));
+               fmb.setPriority(U16.t(LB_PRIORITY));
 
-               OFMatch ofMatch = new OFMatch();
+               Match match = null;
                try {
-                   ofMatch.fromString(matchString);
+                   match = MatchString.fromString(matchString, switchService.getSwitch(sw).getOFFactory().getVersion());
                } catch (IllegalArgumentException e) {
-                   log.debug("ignoring flow entry {} on switch {} with illegal OFMatch() key: "
-                                     + matchString, entryName, swString);
+                   log.debug("ignoring flow entry {} on switch {} with illegal OFMatch() key: " + matchString, entryName, swString);
                }
         
-               fm.setMatch(ofMatch);
-               sfp.addFlow(entryName, fm, swString);
+               fmb.setMatch(match);
+               sfpService.addFlow(entryName, fmb.build(), swString);
 
            }
         }
@@ -809,8 +800,9 @@ public class LoadBalancer implements IFloodlightModule,
                 new ArrayList<Class<? extends IFloodlightService>>();
         l.add(IFloodlightProviderService.class);
         l.add(IRestApiService.class);
-        l.add(ICounterStoreService.class);
+        l.add(IOFSwitchService.class);
         l.add(IDeviceService.class);
+        l.add(IDebugCounterService.class);
         l.add(ITopologyService.class);
         l.add(IRoutingService.class);
         l.add(IStaticFlowEntryPusherService.class);
@@ -821,13 +813,14 @@ public class LoadBalancer implements IFloodlightModule,
     @Override
     public void init(FloodlightModuleContext context)
                                                  throws FloodlightModuleException {
-        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-        restApi = context.getServiceImpl(IRestApiService.class);
-        counterStore = context.getServiceImpl(ICounterStoreService.class);
-        deviceManager = context.getServiceImpl(IDeviceService.class);
-        routingEngine = context.getServiceImpl(IRoutingService.class);
-        topology = context.getServiceImpl(ITopologyService.class);
-        sfp = context.getServiceImpl(IStaticFlowEntryPusherService.class);
+        floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
+        restApiService = context.getServiceImpl(IRestApiService.class);
+        debugCounterService = context.getServiceImpl(IDebugCounterService.class);
+        deviceManagerService = context.getServiceImpl(IDeviceService.class);
+        routingEngineService = context.getServiceImpl(IRoutingService.class);
+        topologyService = context.getServiceImpl(ITopologyService.class);
+        sfpService = context.getServiceImpl(IStaticFlowEntryPusherService.class);
+        switchService = context.getServiceImpl(IOFSwitchService.class);
         
         messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY, 
                                             EnumSet.of(OFType.FLOW_MOD),
@@ -843,15 +836,14 @@ public class LoadBalancer implements IFloodlightModule,
 
     @Override
     public void startUp(FloodlightModuleContext context) {
-        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-        restApi.addRestletRoutable(new LoadBalancerWebRoutable());
+        floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);
+        restApiService.addRestletRoutable(new LoadBalancerWebRoutable());
     }
 
     // Utilities borrowed from StaticFlowEntries
     
     private static class SubActionStruct {
         OFAction action;
-        int      len;
     }
     
     /**
@@ -862,7 +854,7 @@ public class LoadBalancer implements IFloodlightModule,
      */
     public static void parseActionString(OFFlowMod flowMod, String actionstr, Logger log) {
         List<OFAction> actions = new LinkedList<OFAction>();
-        int actionsLength = 0;
+        OFVersion version = flowMod.getVersion();
         if (actionstr != null) {
             actionstr = actionstr.toLowerCase();
             for (String subaction : actionstr.split(",")) {
@@ -870,40 +862,40 @@ public class LoadBalancer implements IFloodlightModule,
                 SubActionStruct subaction_struct = null;
                 
                 if (action.equals("output")) {
-                    subaction_struct = decode_output(subaction, log);
+                    subaction_struct = decode_output(subaction, version, log);
                 }
                 else if (action.equals("enqueue")) {
-                    subaction_struct = decode_enqueue(subaction, log);
+                    subaction_struct = decode_enqueue(subaction, version, log);
                 }
                 else if (action.equals("strip-vlan")) {
-                    subaction_struct = decode_strip_vlan(subaction, log);
+                    subaction_struct = decode_strip_vlan(subaction, version, log);
                 }
                 else if (action.equals("set-vlan-id")) {
-                    subaction_struct = decode_set_vlan_id(subaction, log);
+                    subaction_struct = decode_set_vlan_id(subaction, version, log);
                 }
                 else if (action.equals("set-vlan-priority")) {
-                    subaction_struct = decode_set_vlan_priority(subaction, log);
+                    subaction_struct = decode_set_vlan_priority(subaction, version, log);
                 }
                 else if (action.equals("set-src-mac")) {
-                    subaction_struct = decode_set_src_mac(subaction, log);
+                    subaction_struct = decode_set_src_mac(subaction, version, log);
                 }
                 else if (action.equals("set-dst-mac")) {
-                    subaction_struct = decode_set_dst_mac(subaction, log);
+                    subaction_struct = decode_set_dst_mac(subaction, version, log);
                 }
                 else if (action.equals("set-tos-bits")) {
-                    subaction_struct = decode_set_tos_bits(subaction, log);
+                    subaction_struct = decode_set_tos_bits(subaction, version, log);
                 }
                 else if (action.equals("set-src-ip")) {
-                    subaction_struct = decode_set_src_ip(subaction, log);
+                    subaction_struct = decode_set_src_ip(subaction, version, log);
                 }
                 else if (action.equals("set-dst-ip")) {
-                    subaction_struct = decode_set_dst_ip(subaction, log);
+                    subaction_struct = decode_set_dst_ip(subaction, version, log);
                 }
                 else if (action.equals("set-src-port")) {
-                    subaction_struct = decode_set_src_port(subaction, log);
+                    subaction_struct = decode_set_src_port(subaction, version, log);
                 }
                 else if (action.equals("set-dst-port")) {
-                    subaction_struct = decode_set_dst_port(subaction, log);
+                    subaction_struct = decode_set_dst_port(subaction, version, log);
                 }
                 else {
                     log.error("Unexpected action '{}', '{}'", action, subaction);
@@ -911,28 +903,25 @@ public class LoadBalancer implements IFloodlightModule,
                 
                 if (subaction_struct != null) {
                     actions.add(subaction_struct.action);
-                    actionsLength += subaction_struct.len;
                 }
             }
         }
         log.debug("action {}", actions);
         
-        flowMod.setActions(actions);
-        flowMod.setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLength);
+        flowMod = flowMod.createBuilder().setActions(actions).build();
     } 
     
-    private static SubActionStruct decode_output(String subaction, Logger log) {
+    private static SubActionStruct decode_output(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n;
         
         n = Pattern.compile("output=(?:((?:0x)?\\d+)|(all)|(controller)|(local)|(ingress-port)|(normal)|(flood))").matcher(subaction);
         if (n.matches()) {
-            OFActionOutput action = new OFActionOutput();
-            action.setMaxLength(Short.MAX_VALUE);
-            short port = OFPort.OFPP_NONE.getValue();
+            OFActionOutput.Builder ab = OFFactories.getFactory(version).actions().buildOutput();
+            OFPort port = OFPort.ANY; //TODO @Ryan is ANY == NONE?
             if (n.group(1) != null) {
                 try {
-                    port = get_short(n.group(1));
+                    port = OFPort.of(get_short(n.group(1)));
                 }
                 catch (NumberFormatException e) {
                     log.debug("Invalid port in: '{}' (error ignored)", subaction);
@@ -940,23 +929,22 @@ public class LoadBalancer implements IFloodlightModule,
                 }
             }
             else if (n.group(2) != null)
-                port = OFPort.OFPP_ALL.getValue();
+                port = OFPort.ALL;
             else if (n.group(3) != null)
-                port = OFPort.OFPP_CONTROLLER.getValue();
+                port = OFPort.CONTROLLER;
             else if (n.group(4) != null)
-                port = OFPort.OFPP_LOCAL.getValue();
+                port = OFPort.LOCAL;
             else if (n.group(5) != null)
-                port = OFPort.OFPP_IN_PORT.getValue();
+                port = OFPort.IN_PORT;
             else if (n.group(6) != null)
-                port = OFPort.OFPP_NORMAL.getValue();
+                port = OFPort.NORMAL;
             else if (n.group(7) != null)
-                port = OFPort.OFPP_FLOOD.getValue();
-            action.setPort(port);
-            log.debug("action {}", action);
+                port = OFPort.FLOOD;
+            ab.setPort(port);
+            log.debug("action {}", ab.build());
             
             sa = new SubActionStruct();
-            sa.action = action;
-            sa.len = OFActionOutput.MINIMUM_LENGTH;
+            sa.action = ab.build();
         }
         else {
             log.error("Invalid subaction: '{}'", subaction);
@@ -966,16 +954,16 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
     
-    private static SubActionStruct decode_enqueue(String subaction, Logger log) {
+    private static SubActionStruct decode_enqueue(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n;
         
         n = Pattern.compile("enqueue=(?:((?:0x)?\\d+)\\:((?:0x)?\\d+))").matcher(subaction);
         if (n.matches()) {
-            short portnum = 0;
+            OFPort portnum = OFPort.of(0);
             if (n.group(1) != null) {
                 try {
-                    portnum = get_short(n.group(1));
+                    portnum = OFPort.of(get_short(n.group(1)));
                 }
                 catch (NumberFormatException e) {
                     log.debug("Invalid port-num in: '{}' (error ignored)", subaction);
@@ -994,14 +982,13 @@ public class LoadBalancer implements IFloodlightModule,
                }
             }
             
-            OFActionEnqueue action = new OFActionEnqueue();
-            action.setPort(portnum);
-            action.setQueueId(queueid);
-            log.debug("action {}", action);
+            OFActionEnqueue.Builder aeb = OFFactories.getFactory(version).actions().buildEnqueue();
+            aeb.setPort(portnum);
+            aeb.setQueueId(queueid);
+            log.debug("action {}", aeb.build());
             
             sa = new SubActionStruct();
-            sa.action = action;
-            sa.len = OFActionEnqueue.MINIMUM_LENGTH;
+            sa.action = aeb.build();
         }
         else {
             log.debug("Invalid action: '{}'", subaction);
@@ -1011,17 +998,16 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
     
-    private static SubActionStruct decode_strip_vlan(String subaction, Logger log) {
+    private static SubActionStruct decode_strip_vlan(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("strip-vlan").matcher(subaction);
         
         if (n.matches()) {
-            OFActionStripVirtualLan action = new OFActionStripVirtualLan();
-            log.debug("action {}", action);
+            OFActionStripVlan asvl = OFFactories.getFactory(version).actions().stripVlan();
+            log.debug("action {}", asvl);
             
             sa = new SubActionStruct();
-            sa.action = action;
-            sa.len = OFActionStripVirtualLan.MINIMUM_LENGTH;
+            sa.action = asvl;
         }
         else {
             log.debug("Invalid action: '{}'", subaction);
@@ -1031,7 +1017,7 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
     
-    private static SubActionStruct decode_set_vlan_id(String subaction, Logger log) {
+    private static SubActionStruct decode_set_vlan_id(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-vlan-id=((?:0x)?\\d+)").matcher(subaction);
         
@@ -1039,13 +1025,12 @@ public class LoadBalancer implements IFloodlightModule,
             if (n.group(1) != null) {
                 try {
                     short vlanid = get_short(n.group(1));
-                    OFActionVirtualLanIdentifier action = new OFActionVirtualLanIdentifier();
-                    action.setVirtualLanIdentifier(vlanid);
-                    log.debug("  action {}", action);
+                    OFActionSetVlanVid.Builder avvid = OFFactories.getFactory(version).actions().buildSetVlanVid();
+                    avvid.setVlanVid(VlanVid.ofVlan(vlanid));
+                    log.debug("  action {}", avvid.build());
 
                     sa = new SubActionStruct();
-                    sa.action = action;
-                    sa.len = OFActionVirtualLanIdentifier.MINIMUM_LENGTH;
+                    sa.action = avvid.build();
                 }
                 catch (NumberFormatException e) {
                     log.debug("Invalid VLAN in: {} (error ignored)", subaction);
@@ -1061,7 +1046,7 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
     
-    private static SubActionStruct decode_set_vlan_priority(String subaction, Logger log) {
+    private static SubActionStruct decode_set_vlan_priority(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-vlan-priority=((?:0x)?\\d+)").matcher(subaction); 
         
@@ -1069,13 +1054,12 @@ public class LoadBalancer implements IFloodlightModule,
             if (n.group(1) != null) {
                 try {
                     byte prior = get_byte(n.group(1));
-                    OFActionVirtualLanPriorityCodePoint action = new OFActionVirtualLanPriorityCodePoint();
-                    action.setVirtualLanPriorityCodePoint(prior);
-                    log.debug("  action {}", action);
+                    OFActionSetVlanPcp.Builder avpcp = OFFactories.getFactory(version).actions().buildSetVlanPcp();
+                    avpcp.setVlanPcp(VlanPcp.of(prior));
+                    log.debug("  action {}", avpcp.build());
                     
                     sa = new SubActionStruct();
-                    sa.action = action;
-                    sa.len = OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH;
+                    sa.action = avpcp.build();
                 }
                 catch (NumberFormatException e) {
                     log.debug("Invalid VLAN priority in: {} (error ignored)", subaction);
@@ -1091,20 +1075,19 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
     
-    private static SubActionStruct decode_set_src_mac(String subaction, Logger log) {
+    private static SubActionStruct decode_set_src_mac(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-src-mac=(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(subaction); 
 
         if (n.matches()) {
             byte[] macaddr = get_mac_addr(n, subaction, log);
             if (macaddr != null) {
-                OFActionDataLayerSource action = new OFActionDataLayerSource();
-                action.setDataLayerAddress(macaddr);
-                log.debug("action {}", action);
+                OFActionSetDlSrc.Builder asdls = OFFactories.getFactory(version).actions().buildSetDlSrc();
+                asdls.setDlAddr(MacAddress.of(macaddr));
+                log.debug("action {}", asdls.build());
 
                 sa = new SubActionStruct();
-                sa.action = action;
-                sa.len = OFActionDataLayerSource.MINIMUM_LENGTH;
+                sa.action = asdls.build();
             }
         }
         else {
@@ -1115,20 +1098,19 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
 
-    private static SubActionStruct decode_set_dst_mac(String subaction, Logger log) {
+    private static SubActionStruct decode_set_dst_mac(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-dst-mac=(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(subaction);
         
         if (n.matches()) {
             byte[] macaddr = get_mac_addr(n, subaction, log);
             if (macaddr != null) {
-                OFActionDataLayerDestination action = new OFActionDataLayerDestination();
-                action.setDataLayerAddress(macaddr);
-                log.debug("  action {}", action);
+                OFActionSetDlDst.Builder asdld = OFFactories.getFactory(version).actions().buildSetDlDst();
+                asdld.setDlAddr(MacAddress.of(macaddr));
+                log.debug("  action {}", asdld.build());
                 
                 sa = new SubActionStruct();
-                sa.action = action;
-                sa.len = OFActionDataLayerDestination.MINIMUM_LENGTH;
+                sa.action = asdld.build();
             }
         }
         else {
@@ -1139,7 +1121,7 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
     
-    private static SubActionStruct decode_set_tos_bits(String subaction, Logger log) {
+    private static SubActionStruct decode_set_tos_bits(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-tos-bits=((?:0x)?\\d+)").matcher(subaction); 
 
@@ -1147,13 +1129,12 @@ public class LoadBalancer implements IFloodlightModule,
             if (n.group(1) != null) {
                 try {
                     byte tosbits = get_byte(n.group(1));
-                    OFActionNetworkTypeOfService action = new OFActionNetworkTypeOfService();
-                    action.setNetworkTypeOfService(tosbits);
-                    log.debug("  action {}", action);
+                    OFActionSetNwTos.Builder snwtos = OFFactories.getFactory(version).actions().buildSetNwTos();
+                    snwtos.setNwTos(tosbits);
+                    log.debug("  action {}", snwtos.build());
                     
                     sa = new SubActionStruct();
-                    sa.action = action;
-                    sa.len = OFActionNetworkTypeOfService.MINIMUM_LENGTH;
+                    sa.action = snwtos.build();
                 }
                 catch (NumberFormatException e) {
                     log.debug("Invalid dst-port in: {} (error ignored)", subaction);
@@ -1169,19 +1150,18 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
     
-    private static SubActionStruct decode_set_src_ip(String subaction, Logger log) {
+    private static SubActionStruct decode_set_src_ip(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-src-ip=(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(subaction);
 
         if (n.matches()) {
             int ipaddr = get_ip_addr(n, subaction, log);
-            OFActionNetworkLayerSource action = new OFActionNetworkLayerSource();
-            action.setNetworkAddress(ipaddr);
-            log.debug("  action {}", action);
+            OFActionSetNwSrc.Builder snws = OFFactories.getFactory(version).actions().buildSetNwSrc();
+            snws.setNwAddr(IPv4Address.of(ipaddr));
+            log.debug("  action {}", snws.build());
 
             sa = new SubActionStruct();
-            sa.action = action;
-            sa.len = OFActionNetworkLayerSource.MINIMUM_LENGTH;
+            sa.action = snws.build();
         }
         else {
             log.debug("Invalid action: '{}'", subaction);
@@ -1191,19 +1171,18 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
 
-    private static SubActionStruct decode_set_dst_ip(String subaction, Logger log) {
+    private static SubActionStruct decode_set_dst_ip(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-dst-ip=(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(subaction);
 
         if (n.matches()) {
             int ipaddr = get_ip_addr(n, subaction, log);
-            OFActionNetworkLayerDestination action = new OFActionNetworkLayerDestination();
-            action.setNetworkAddress(ipaddr);
-            log.debug("action {}", action);
+            OFActionSetNwDst.Builder snwd = OFFactories.getFactory(version).actions().buildSetNwDst();
+            snwd.setNwAddr(IPv4Address.of(ipaddr));
+            log.debug("action {}", snwd.build());
  
             sa = new SubActionStruct();
-            sa.action = action;
-            sa.len = OFActionNetworkLayerDestination.MINIMUM_LENGTH;
+            sa.action = snwd.build();
         }
         else {
             log.debug("Invalid action: '{}'", subaction);
@@ -1213,21 +1192,20 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
 
-    private static SubActionStruct decode_set_src_port(String subaction, Logger log) {
+    private static SubActionStruct decode_set_src_port(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-src-port=((?:0x)?\\d+)").matcher(subaction); 
 
         if (n.matches()) {
             if (n.group(1) != null) {
                 try {
-                    short portnum = get_short(n.group(1));
-                    OFActionTransportLayerSource action = new OFActionTransportLayerSource();
-                    action.setTransportPort(portnum);
-                    log.debug("action {}", action);
+                    TransportPort portnum = TransportPort.of(get_short(n.group(1)));
+                    OFActionSetTpSrc.Builder stps = OFFactories.getFactory(version).actions().buildSetTpSrc();
+                    stps.setTpPort(portnum);
+                    log.debug("action {}", stps.build());
                     
                     sa = new SubActionStruct();
-                    sa.action = action;
-                    sa.len = OFActionTransportLayerSource.MINIMUM_LENGTH;;
+                    sa.action = stps.build();
                 }
                 catch (NumberFormatException e) {
                     log.debug("Invalid src-port in: {} (error ignored)", subaction);
@@ -1243,21 +1221,20 @@ public class LoadBalancer implements IFloodlightModule,
         return sa;
     }
 
-    private static SubActionStruct decode_set_dst_port(String subaction, Logger log) {
+    private static SubActionStruct decode_set_dst_port(String subaction, OFVersion version, Logger log) {
         SubActionStruct sa = null;
         Matcher n = Pattern.compile("set-dst-port=((?:0x)?\\d+)").matcher(subaction);
 
         if (n.matches()) {
             if (n.group(1) != null) {
                 try {
-                    short portnum = get_short(n.group(1));
-                    OFActionTransportLayerDestination action = new OFActionTransportLayerDestination();
-                    action.setTransportPort(portnum);
-                    log.debug("action {}", action);
+                    TransportPort portnum = TransportPort.of(get_short(n.group(1)));
+                    OFActionSetTpDst.Builder stpd = OFFactories.getFactory(version).actions().buildSetTpDst();
+                    stpd.setTpPort(portnum);
+                    log.debug("action {}", stpd);
                     
                     sa = new SubActionStruct();
-                    sa.action = action;
-                    sa.len = OFActionTransportLayerDestination.MINIMUM_LENGTH;;
+                    sa.action = stpd.build();
                 }
                 catch (NumberFormatException e) {
                     log.debug("Invalid dst-port in: {} (error ignored)", subaction);
diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
index 1c273f826..abd7e8bf1 100644
--- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
+++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
@@ -113,7 +113,7 @@ public abstract class ForwardingBase
     static {
         AppCookie.registerApp(FORWARDING_APP_ID, "Forwarding");
     }
-    public static final long appCookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0);
+    public static final U64 appCookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0);
 
     // Comparator for sorting by SwitchCluster
     public Comparator<SwitchPort> clusterIdComparator =
-- 
GitLab