From 2a1fbbf2123381cc9a7faae93110a1719b7b4449 Mon Sep 17 00:00:00 2001
From: Ryan Izard <rizard@g.clemson.edu>
Date: Mon, 4 Aug 2014 16:39:31 -0700
Subject: [PATCH] Removed BSN-specific handshakes, some debug messages, tweaked
 static flow entry pusher, and hub to work with new OpenFlowJ-Loxi flow mod
 commands.

---
 .../core/GenTableMap.java                     |  136 -
 .../core/GenTableNotFoundException.java       |   44 -
 .../floodlightcontroller/core/IOFSwitch.java  |    2 -
 .../core/IOFSwitchBackend.java                |    3 -
 .../core/OFConnection.java                    |    1 -
 .../floodlightcontroller/core/OFSwitch.java   |   14 -
 .../core/internal/OFChannelHandler.java       | 1402 +++----
 .../internal/OFSwitchHandshakeHandler.java    | 3307 ++++++++---------
 .../core/internal/OFSwitchManager.java        |    3 +-
 .../net/floodlightcontroller/hub/Hub.java     |   37 +-
 .../IStaticFlowEntryPusherService.java        |    4 +-
 .../staticflowentry/StaticFlowEntries.java    |   33 +-
 .../StaticFlowEntryPusher.java                |   50 +-
 .../web/ListStaticFlowEntriesResource.java    |    3 +-
 .../testmodule/TestModule.java                |   81 +
 .../util/FlowModUtils.java                    |  119 +
 ...htcontroller.core.module.IFloodlightModule |    4 +-
 .../resources/floodlightdefault.properties    |    5 +-
 18 files changed, 2470 insertions(+), 2778 deletions(-)
 delete mode 100644 src/main/java/net/floodlightcontroller/core/GenTableMap.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java
 create mode 100644 src/main/java/net/floodlightcontroller/testmodule/TestModule.java
 create mode 100644 src/main/java/net/floodlightcontroller/util/FlowModUtils.java

diff --git a/src/main/java/net/floodlightcontroller/core/GenTableMap.java b/src/main/java/net/floodlightcontroller/core/GenTableMap.java
deleted file mode 100644
index ef32a1979..000000000
--- a/src/main/java/net/floodlightcontroller/core/GenTableMap.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package net.floodlightcontroller.core;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.concurrent.Immutable;
-
-import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsEntry;
-import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsRequest;
-import org.projectfloodlight.openflow.types.GenTableId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableMap;
-
-/** A registry for GenTables. Initialized during switch handshake, based on a
- *  {@link OFBsnGentableDescStatsRequest}. The table for a particular switch
- *  can be retrieved via {@link IOFSwitch#getGenTableMap()}.
- *
- * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
- */
-@Immutable
-public class GenTableMap {
-    private static final Logger logger = LoggerFactory.getLogger(GenTableMap.class);
-
-    private final Map<GenTableId, OFBsnGentableDescStatsEntry> idMap;
-    private final Map<String, OFBsnGentableDescStatsEntry> nameMap;
-
-    // an empty gentable map
-    private GenTableMap() {
-        idMap = ImmutableMap.of();
-        nameMap = ImmutableMap.of();
-    }
-
-    public GenTableMap(Iterable<OFBsnGentableDescStatsEntry> entries) {
-        // note: not using an ImmutableMap.Builder here, because we need to
-        // check for duplicates
-        Map<GenTableId, OFBsnGentableDescStatsEntry> idBuildMap = new LinkedHashMap<>();
-        Map<String, OFBsnGentableDescStatsEntry> nameBuildMap = new LinkedHashMap<>();
-
-        for (OFBsnGentableDescStatsEntry e : entries) {
-            GenTableId id = e.getTableId();
-            String name = e.getName();
-            if (idBuildMap.containsKey(id)) {
-                logger.warn("Duplicate table id " + id + " - entry {} present. Ignoring new entry {}",
-                        idBuildMap.get(id), e);
-                continue;
-            }
-            if (nameBuildMap.containsKey(name)) {
-                logger.warn(
-                        "Duplicate table name " + name + " - entry named {} present. Ignoring new entry {}",
-                        nameBuildMap.get(name), e);
-                continue;
-            }
-            idBuildMap.put(id, e);
-            nameBuildMap.put(name, e);
-        }
-        this.idMap = ImmutableMap.copyOf(idBuildMap);
-        this.nameMap = ImmutableMap.copyOf(nameBuildMap);
-    }
-
-    public Set<GenTableId> getIds() {
-        return idMap.keySet();
-    }
-
-    public Set<String> getNames() {
-        return nameMap.keySet();
-    }
-
-    public Collection<OFBsnGentableDescStatsEntry> getEntries() {
-        return idMap.values();
-    }
-
-    public boolean hasEntry(GenTableId id) {
-        return idMap.containsKey(id);
-    }
-
-    /** retrieve a GenTable Description from the map by id.
-     *
-     * @param id
-     * @return the retrieved gen  table description.
-     * @throws GenTableNotFoundException if no gentable with the given id was found in the map
-     */
-    @Nonnull
-    public OFBsnGentableDescStatsEntry getEntry(GenTableId id) throws GenTableNotFoundException {
-        OFBsnGentableDescStatsEntry entry = idMap.get(id);
-        if(entry == null)
-            throw new GenTableNotFoundException(id, idMap.values());
-        return entry;
-    }
-
-    public boolean hasEntry(String name) {
-        return nameMap.containsKey(name);
-    }
-
-    /** retrieve a GenTable Description from the map by name.
-     *
-     * @param name
-     * @return the retrieved gen table description.
-     * @throws GenTableNotFoundException if no gentable with the given name was found in the map
-     */
-    @Nonnull
-    public OFBsnGentableDescStatsEntry getEntry(String name) throws GenTableNotFoundException {
-        OFBsnGentableDescStatsEntry entry = nameMap.get(name);
-        if(entry == null)
-            throw new GenTableNotFoundException(name, nameMap.values());
-        return entry;
-    }
-
-    public final static GenTableMap empty() {
-        return new GenTableMap();
-    }
-
-    public static GenTableMap of(Iterable<OFBsnGentableDescStatsReply> replies) {
-        List<OFBsnGentableDescStatsEntry> allEntries = new ArrayList<>();
-        for(OFBsnGentableDescStatsReply reply: replies) {
-            allEntries.addAll(reply.getEntries());
-        }
-        return new GenTableMap(allEntries);
-    }
-
-    @Override
-    public String toString() {
-        return idMap.toString();
-    }
-
-    public int size() {
-        return idMap.size();
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java b/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java
deleted file mode 100644
index 544fc1e84..000000000
--- a/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package net.floodlightcontroller.core;
-
-import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsEntry;
-import org.projectfloodlight.openflow.types.GenTableId;
-
-/** A GenTable was not found in the {@link GenTableMap}.
- *
- * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
- */
-public class GenTableNotFoundException extends RuntimeException {
-    private static final long serialVersionUID = 1L;
-
-    public GenTableNotFoundException(String name, Iterable<OFBsnGentableDescStatsEntry> available) {
-        super(getMessageForName(name, available));
-    }
-
-    private static String getMessageForName(String name,
-            Iterable<OFBsnGentableDescStatsEntry> available) {
-        return String.format("Table not found: %s (available tables: %s)", name, availableDescr(available));
-    }
-
-    public GenTableNotFoundException(GenTableId id, Iterable<OFBsnGentableDescStatsEntry> available) {
-        super(getMessageForId(id, available));
-    }
-
-    private static String getMessageForId(GenTableId id,
-            Iterable<OFBsnGentableDescStatsEntry> available) {
-        return String.format("Table not found: %s (available tables: %s)", id, availableDescr(available));
-    }
-
-    private static String availableDescr(Iterable<OFBsnGentableDescStatsEntry> available) {
-        StringBuilder b = new StringBuilder();
-        boolean first = true;
-        for(OFBsnGentableDescStatsEntry e: available) {
-            if(!first)
-                b.append(", ");
-            first = false;
-            b.append(e.getName()).append("=").append(e.getTableId());
-        }
-        return b.toString();
-    }
-
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
index 165df6ea1..1bd6a5e72 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
@@ -111,8 +111,6 @@ public interface IOFSwitch extends IOFMessageWriter {
 
     Set<OFCapabilities> getCapabilities();
 
-    GenTableMap getGenTableMap();
-
     short getTables();
 
     /**
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
index 58cc62786..d16c5e20f 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
@@ -61,9 +61,6 @@ public interface IOFSwitchBackend extends IOFSwitch {
      */
     void setFeaturesReply(OFFeaturesReply featuresReply);
 
-    /** set the gentable mapping for this switch */
-    void setGenTableMap(GenTableMap map);
-
     /**
      * Add or modify a switch port.
      * This is called by the core controller
diff --git a/src/main/java/net/floodlightcontroller/core/OFConnection.java b/src/main/java/net/floodlightcontroller/core/OFConnection.java
index 58a6a1f82..e53c7dfd0 100644
--- a/src/main/java/net/floodlightcontroller/core/OFConnection.java
+++ b/src/main/java/net/floodlightcontroller/core/OFConnection.java
@@ -114,7 +114,6 @@ 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);
diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
index 332f4725c..71bc04e6b 100644
--- a/src/main/java/net/floodlightcontroller/core/OFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
@@ -113,8 +113,6 @@ public class OFSwitch implements IOFSwitchBackend {
 
     protected SwitchDescription description;
 
-    private GenTableMap genTableMap;
-
     private SwitchStatus status;
 
     public static final int OFSWITCH_APP_ID = ident(5);
@@ -142,7 +140,6 @@ public class OFSwitch implements IOFSwitchBackend {
         this.role = null;
         this.description = new SwitchDescription();
         this.portManager = new PortManager();
-        this.genTableMap = GenTableMap.empty();
         this.status = SwitchStatus.HANDSHAKE;
 
         // Connections
@@ -561,7 +558,6 @@ public class OFSwitch implements IOFSwitchBackend {
                                 String.format("%s (%d)", duplicatePort.getName(), duplicatePort.getPortNo().getPortNumber()));
                         throw new IllegalArgumentException(msg);
                     }
-                    //TODO @Ryan How to handle port state?
                     // Enabled = not down admin (config) or phys (state)
                     if (!p.getConfig().contains(OFPortConfig.PORT_DOWN)
                     		&& !p.getState().contains(OFPortState.LINK_DOWN)) {
@@ -1035,16 +1031,6 @@ public class OFSwitch implements IOFSwitchBackend {
             throw new SwitchDriverSubHandshakeNotStarted();
     }
 
-    @Override
-    public GenTableMap getGenTableMap() {
-        return genTableMap;
-    }
-
-    @Override
-    public void setGenTableMap(GenTableMap map) {
-        this.genTableMap = map;
-    }
-
     @Override
     public void setSwitchProperties(SwitchDescription description) {
         this.description = description;
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
index 8be6c6745..ca76c6af5 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
@@ -54,706 +54,706 @@ import com.google.common.base.Preconditions;
  */
 class OFChannelHandler extends IdleStateAwareChannelHandler {
 
-    private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
-
-    private final ChannelPipeline pipeline;
-    private final INewOFConnectionListener newConnectionListener;
-    private final SwitchManagerCounters counters;
-    private Channel channel;
-    private final Timer timer;
-    private volatile OFChannelState state;
-    private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
-    private OFFeaturesReply featuresReply;
-    private volatile OFConnection connection;
-    private final IDebugCounterService debugCounters;
-
-    /** transaction Ids to use during handshake. Since only one thread
-     * calls into the OFChannelHandler we don't need atomic.
-     * We will count down
-     */
-    private long handshakeTransactionIds = 0x00FFFFFFFFL;
-
-
-    /**
-     * Default implementation for message handlers in any OFChannelState.
-     *
-     * Individual states must override these if they want a behavior
-     * that differs from the default.
-     */
-    public abstract class OFChannelState {
-
-        void processOFHello(OFHello m)
-                throws IOException {
-            // we only expect hello in the WAIT_HELLO state
-            illegalMessageReceived(m);
-        }
-
-        void processOFEchoRequest(OFEchoRequest m)
-                throws IOException {
-            sendEchoReply(m);
-        }
-
-        void processOFEchoReply(OFEchoReply m)
-            throws IOException {
-            // do nothing
-        }
-
-        void processOFError(OFErrorMsg m) {
-            logErrorDisconnect(m);
-        }
-
-        void processOFExperimenter(OFExperimenter m) {
-           unhandledMessageReceived(m);
-        }
-
-        void processOFFeaturesReply(OFFeaturesReply  m)
-                throws IOException {
-         // we only expect features reply in the WAIT_FEATURES_REPLY state
-            illegalMessageReceived(m);
-        }
-
-        private final boolean channelHandshakeComplete;
-
-        OFChannelState(boolean handshakeComplete) {
-            this.channelHandshakeComplete = handshakeComplete;
-        }
-
-        void logState() {
-            log.debug("{} OFConnection Handshake - enter state {}",
-                    getConnectionInfoString(), this.getClass().getSimpleName());
-        }
-
-        /** enter this state. Can initialize the handler, send
-         *  the necessary messages, etc.
-         * @throws IOException
-         */
-        void enterState() throws IOException{
-            // Do Nothing
-        }
-
-        /**
-         * Get a string specifying the switch connection, state, and
-         * message received. To be used as message for SwitchStateException
-         * or log messages
-         * @param h The channel handler (to get switch information_
-         * @param m The OFMessage that has just been received
-         * @param details A string giving more details about the exact nature
-         * of the problem.
-         * @return
-         */
-        // needs to be protected because enum members are acutally subclasses
-        protected String getSwitchStateMessage(OFMessage m,
-                                                      String details) {
-            return String.format("Switch: [%s], State: [%s], received: [%s]"
-                                 + ", details: %s",
-                                 getConnectionInfoString(),
-                                 this.toString(),
-                                 m.getType().toString(),
-                                 details);
-        }
-
-        /**
-         * We have an OFMessage we didn't expect given the current state and
-         * we want to treat this as an error.
-         * We currently throw an exception that will terminate the connection
-         * However, we could be more forgiving
-         * @param h the channel handler that received the message
-         * @param m the message
-         * @throws SwitchStateExeption we always through the execption
-         */
-        // needs to be protected because enum members are acutally subclasses
-        protected void illegalMessageReceived(OFMessage m) {
-            String msg = getSwitchStateMessage(m,
-                    "Switch should never send this message in the current state");
-            throw new SwitchStateException(msg);
-
-        }
-
-        /**
-         * We have an OFMessage we didn't expect given the current state and
-         * we want to ignore the message
-         * @param h the channel handler the received the message
-         * @param m the message
-         */
-        protected void unhandledMessageReceived(OFMessage m) {
-            counters.unhandledMessage.increment();
-            if (log.isDebugEnabled()) {
-                String msg = getSwitchStateMessage(m,
-                        "Ignoring unexpected message");
-                log.debug(msg);
-            }
-        }
-
-        /**
-         * Log an OpenFlow error message from a switch
-         * @param sw The switch that sent the error
-         * @param error The error message
-         */
-        @LogMessageDoc(level="ERROR",
-                message="Error {error type} {error code} from {switch} " +
-                        "in state {state}",
-                explanation="The switch responded with an unexpected error" +
-                        "to an OpenFlow message from the controller",
-                recommendation="This could indicate improper network operation. " +
-                        "If the problem persists restarting the switch and " +
-                        "controller may help."
-                )
-        protected void logError(OFErrorMsg error) {
-            log.error("{} from switch {} in state {}",
-                      new Object[] {
-                          error.toString(),
-                          getConnectionInfoString(),
-                          this.toString()});
-        }
-
-        /**
-         * Log an OpenFlow error message from a switch and disconnect the
-         * channel
-         * @param sw The switch that sent the error
-         * @param error The error message
-         */
-        protected void logErrorDisconnect(OFErrorMsg error) {
-            logError(error);
-            channel.disconnect();
-        }
-
-        /**
-         * Process an OF message received on the channel and
-         * update state accordingly.
-         *
-         * The main "event" of the state machine. Process the received message,
-         * send follow up message if required and update state if required.
-         *
-         * Switches on the message type and calls more specific event handlers
-         * for each individual OF message type. If we receive a message that
-         * is supposed to be sent from a controller to a switch we throw
-         * a SwitchStateExeption.
-         *
-         * The more specific handlers can also throw SwitchStateExceptions
-         *
-         * @param h The OFChannelHandler that received the message
-         * @param m The message we received.
-         * @throws SwitchStateException
-         * @throws IOException
-         */
-        void processOFMessage(OFMessage m)
-                throws IOException {
-            // Handle Channel Handshake
-            if (!state.channelHandshakeComplete) {
-            switch(m.getType()) {
-                case HELLO:
-                    processOFHello((OFHello)m);
-                    break;
-                case ERROR:
-                    processOFError((OFErrorMsg)m);
-                    break;
-                case FEATURES_REPLY:
-                    processOFFeaturesReply((OFFeaturesReply)m);
-                    break;
-                case EXPERIMENTER:
-                    processOFExperimenter((OFExperimenter)m);
-                    break;
-                default:
-                    illegalMessageReceived(m);
-                    break;
-                }
-            }
-            else{
-                switch(m.getType()){
-                    // Always handle echos at the channel level!
-                    // Echos should only be sent in the complete.
-                    case ECHO_REPLY:
-                        processOFEchoReply((OFEchoReply)m);
-                        break;
-                    case ECHO_REQUEST:
-                        processOFEchoRequest((OFEchoRequest)m);
-                        break;
-                    // Send to SwitchManager and thus higher orders of control
-                    default:
-                        sendMessageToConnection(m);
-                        break;
-                }
-            }
-        }
-    }
-
-    /**
-     * Initial state before channel is connected.
-     */
-      class InitState extends OFChannelState {
-
-        InitState() {
-            super(false);
-        }
-    }
-
-        /**
-         * We send a HELLO to the switch and wait for a reply.
-         * Once we receive the reply we send an OFFeaturesRequest
-         * Next state is WaitFeaturesReplyState
-         */
-        class WaitHelloState extends OFChannelState {
-
-        WaitHelloState() {
-            super(false);
-        }
-
-            @Override
-            void processOFHello(OFHello m) throws IOException {
-                OFVersion version = m.getVersion();
-                factory = OFFactories.getFactory(version);
-                OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class);
-                decoder.setVersion(version);
-                setState(new WaitFeaturesReplyState());
-            }
-
-            @Override
-            void enterState() throws IOException {
-                sendHelloMessage();
-            }
-        }
-
-        /**
-         * We are waiting for a features reply message. Once we receive it
-         * we send capture the features reply.
-         * Next state is CompleteState
-         */
-        class WaitFeaturesReplyState extends OFChannelState{
-
-        WaitFeaturesReplyState() {
-            super(false);
-        }
-            @Override
-            void processOFFeaturesReply(OFFeaturesReply  m)
-                    throws IOException {
-                featuresReply = m;
-
-                // Mark handshake as completed
-                setState(new CompleteState());
-
-            }
-            @Override
-            void enterState() throws IOException {
-                sendFeaturesRequest();
-            }
-        };
-
-        /**
-         * This state denotes that the channel handshaking is complete.
-         * An of connection is generated and passed to the switch manager
-         * for handling.
-         */
-        class CompleteState extends OFChannelState{
-
-        CompleteState() {
-            super(true);
-        }
-
-            @Override
-            void enterState() throws IOException{
-
-            setSwitchHandshakeTimeout();
-
-                // Handle non 1.3 connections
-                if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){
-                    connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, OFAuxId.MAIN, debugCounters, timer);
-                }
-                // Handle 1.3 connections
-                else{
-                    connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, featuresReply.getAuxiliaryId(), debugCounters, timer);
-
-                // If this is an aux connection, we set a longer echo idle time
-                if (!featuresReply.getAuxiliaryId().equals(OFAuxId.MAIN)) {
-                    setAuxChannelIdle();
-                }
-                }
-                // Notify the connection broker
-                notifyConnectionOpened(connection);
-
-            }
-        };
-
-    /**
-     * Creates a handler for interacting with the switch channel
-     *
-     * @param controller
-     *            the controller
-     * @param newConnectionListener
-     *            the class that listens for new OF connections (switchManager)
-     * @param pipeline
-     *            the channel pipeline
-     * @param threadPool
-     *            the thread pool
-     * @param idleTimer
-     *            the hash wheeled timer used to send idle messages (echo).
-     *            passed to constructor to modify in case of aux connection.
-     * @param debugCounters
-     */
-    OFChannelHandler(@Nonnull IOFSwitchManager switchManager,
-                     @Nonnull INewOFConnectionListener newConnectionListener,
-                     @Nonnull ChannelPipeline pipeline,
-                     @Nonnull IDebugCounterService debugCounters,
-                     @Nonnull Timer timer) {
-
-        Preconditions.checkNotNull(switchManager, "switchManager");
-        Preconditions.checkNotNull(newConnectionListener, "connectionOpenedListener");
-        Preconditions.checkNotNull(pipeline, "pipeline");
-        Preconditions.checkNotNull(timer, "timer");
-        Preconditions.checkNotNull(debugCounters, "debugCounters");
-
-        this.pipeline = pipeline;
-        this.debugCounters = debugCounters;
-        this.newConnectionListener = newConnectionListener;
-        this.counters = switchManager.getCounters();
-        this.state = new InitState();
-        this.timer = timer;
-
-        log.debug("constructor on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this)));
-    }
-
-    /**
-     * Determines if the entire switch handshake is complete (channel+switch).
-     * If the channel handshake is complete the call is forwarded to the
-     * connection listener/switch manager to be handled by the appropriate
-     * switch handshake handler.
-     *
-     * @return whether or not complete switch handshake is complete
-     */
-    public boolean isSwitchHandshakeComplete() {
-        if (this.state.channelHandshakeComplete) {
-            return connection.getListener().isSwitchHandshakeComplete(connection);
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Notifies the channel listener that we have a valid baseline connection
-     */
-    private final void notifyConnectionOpened(OFConnection connection){
-        this.connection = connection;
-        this.newConnectionListener.connectionOpened(connection, featuresReply);
-    }
-
-    /**
-     * Notifies the channel listener that we our connection has been closed
-     */
-    private final void notifyConnectionClosed(OFConnection connection){
-        connection.getListener().connectionClosed(connection);
-    }
-
-    /**
-     * Notifies the channel listener that we have a valid baseline connection
-     */
-    private final void sendMessageToConnection(OFMessage m) {
-        connection.messageReceived(m);
-    }
-
-    @Override
-    @LogMessageDoc(message="New switch connection from {ip address}",
-                   explanation="A new switch has connected from the " +
-                            "specified IP address")
-    public void channelConnected(ChannelHandlerContext ctx,
-                                 ChannelStateEvent e) throws Exception {
-        log.debug("channelConnected on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this)));
-        counters.switchConnected.increment();
-        channel = e.getChannel();
-        log.info("New switch connection from {}",
-                 channel.getRemoteAddress());
-        setState(new WaitHelloState());
-    }
-
-    @Override
-    @LogMessageDoc(message="Disconnected switch {switch information}",
-                   explanation="The specified switch has disconnected.")
-    public void channelDisconnected(ChannelHandlerContext ctx,
-                                    ChannelStateEvent e) throws Exception {
-        // Only handle cleanup connection is even known
-        if(this.connection != null){
-            // Alert the connection object that the channel has been disconnected
-            this.connection.disconnected();
-            // Punt the cleanup to the Switch Manager
-            notifyConnectionClosed(this.connection);
-        }
-        log.info("[{}] Disconnected connection", getConnectionInfoString());
-    }
-
-    @Override
-    @LogMessageDocs({
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to read timeout",
-                explanation="The connected switch has failed to send any " +
-                            "messages or respond to echo requests",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch}: failed to " +
-                        "complete handshake",
-                explanation="The switch did not respond correctly " +
-                            "to handshake messages",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to IO Error: {}",
-                explanation="There was an error communicating with the switch",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to switch " +
-                        "state error: {error}",
-                explanation="The switch sent an unexpected message",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to " +
-                        "message parse failure",
-                explanation="Could not parse a message from the switch",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Terminating controller due to storage exception",
-                explanation=Controller.ERROR_DATABASE,
-                recommendation=LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level="ERROR",
-                message="Could not process message: queue full",
-                explanation="OpenFlow messages are arriving faster than " +
-                            " the controller can process them.",
-                recommendation=LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level="ERROR",
-                message="Error while processing message " +
-                        "from switch {switch} {cause}",
-                explanation="An error occurred processing the switch message",
-                recommendation=LogMessageDoc.GENERIC_ACTION)
-    })
-    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
-            throws Exception {
-        if (e.getCause() instanceof ReadTimeoutException) {
-
-            if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
-                log.error("Disconnecting switch {} due to read timeout on main cxn.",
-                          getConnectionInfoString());
-                ctx.getChannel().close();
-            } else {
-                if (featuresReply.getAuxiliaryId().equals(OFAuxId.MAIN)) {
-                    log.error("Disconnecting switch {} due to read timeout on main cxn.",
-                              getConnectionInfoString());
-                    ctx.getChannel().close();
-                } else {
-                    // We only don't disconnect on aux connections
-                    log.warn("Switch {} encountered read timeout on aux cxn.",
-                             getConnectionInfoString());
-                }
-            }
-            // Increment counters
-            counters.switchDisconnectReadTimeout.increment();
-
-        } else if (e.getCause() instanceof HandshakeTimeoutException) {
-            log.error("Disconnecting switch {}: failed to complete handshake. Channel handshake complete : {}",
-                      getConnectionInfoString(),
-                      this.state.channelHandshakeComplete);
-            counters.switchDisconnectHandshakeTimeout.increment();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof ClosedChannelException) {
-            log.debug("Channel for sw {} already closed", getConnectionInfoString());
-        } else if (e.getCause() instanceof IOException) {
-            log.error("Disconnecting switch {} due to IO Error: {}",
-                      getConnectionInfoString(), e.getCause().getMessage());
-            if (log.isDebugEnabled()) {
-                // still print stack trace if debug is enabled
-                log.debug("StackTrace for previous Exception: ", e.getCause());
-            }
-            counters.switchDisconnectIOError.increment();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof SwitchStateException) {
-            log.error("Disconnecting switch {} due to switch state error: {}",
-                      getConnectionInfoString(), e.getCause().getMessage());
-            if (log.isDebugEnabled()) {
-                // still print stack trace if debug is enabled
-                log.debug("StackTrace for previous Exception: ", e.getCause());
-            }
-            counters.switchDisconnectSwitchStateException.increment();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof OFAuxException) {
-            log.error("Disconnecting switch {} due to OF Aux error: {}",
-                      getConnectionInfoString(), e.getCause().getMessage());
-            if (log.isDebugEnabled()) {
-                // still print stack trace if debug is enabled
-                log.debug("StackTrace for previous Exception: ", e.getCause());
-            }
-            counters.switchDisconnectSwitchStateException.increment();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof OFParseError) {
-            log.error("Disconnecting switch "
-                                 + getConnectionInfoString() +
-                                 " due to message parse failure",
-                                 e.getCause());
-            counters.switchDisconnectParseError.increment();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof RejectedExecutionException) {
-            log.warn("Could not process message: queue full");
-            counters.rejectedExecutionException.increment();
-        } else {
-            log.error("Error while processing message from switch "
-                                 + getConnectionInfoString()
-                                 + "state " + this.state, e.getCause());
-            counters.switchDisconnectOtherException.increment();
-            ctx.getChannel().close();
-        }
-    }
-
-    @Override
-    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
-            throws Exception {
-
-        log.debug("channelIdle on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this)));
-        OFChannelHandler handler = ctx.getPipeline().get(OFChannelHandler.class);
-        handler.sendEchoRequest();
-    }
-
-    @Override
-    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
-            throws Exception {
-        if (e.getMessage() instanceof List) {
-            @SuppressWarnings("unchecked")
-            List<OFMessage> msglist = (List<OFMessage>)e.getMessage();
-            for (OFMessage ofm : msglist) {
-                try {
-                    // Do the actual packet processing
-                    state.processOFMessage(ofm);
-                }
-                catch (Exception ex) {
-                    // We are the last handler in the stream, so run the
-                    // exception through the channel again by passing in
-                    // ctx.getChannel().
-                    Channels.fireExceptionCaught(ctx.getChannel(), ex);
-                }
-            }
-        }
-        else {
-            Channels.fireExceptionCaught(ctx.getChannel(),
-                                         new AssertionError("Message received from channel is not a list"));
-        }
-    }
-
-    /**
-     * Sets the channel pipeline's idle (Echo) timeouts to a longer interval.
-     * This is specifically for aux channels.
-     */
-    private void setAuxChannelIdle() {
-
-        IdleStateHandler idleHandler = new IdleStateHandler(
-                                                            this.timer,
-                                                            PipelineIdleReadTimeout.AUX,
-                                                            PipelineIdleWriteTimeout.AUX,
-                                                            0);
-        pipeline.replace(PipelineHandler.MAIN_IDLE,
-                         PipelineHandler.AUX_IDLE,
-                         idleHandler);
-    }
-
-    /**
-     * Sets the channel pipeline's handshake timeout to a more appropriate value
-     * for the remaining part of the switch handshake.
-     */
-    private void setSwitchHandshakeTimeout() {
-
-        HandshakeTimeoutHandler handler = new HandshakeTimeoutHandler(
-                                                                      this,
-                                                                      this.timer,
-                                                                      PipelineHandshakeTimeout.SWITCH);
-
-        pipeline.replace(PipelineHandler.CHANNEL_HANDSHAKE_TIMEOUT,
-                         PipelineHandler.SWITCH_HANDSHAKE_TIMEOUT, handler);
-    }
-
-    /**
-     * Return a string describing this switch based on the already available
-     * information (DPID and/or remote socket)
-     * @return
-     */
-    private String getConnectionInfoString() {
-
-        String channelString;
-        if (channel == null || channel.getRemoteAddress() == null) {
-            channelString = "?";
-        } else {
-            channelString = channel.getRemoteAddress().toString();
-            if(channelString.startsWith("/"))
-                    channelString = channelString.substring(1);
-        }
-        String dpidString;
-        if (featuresReply == null) {
-            dpidString = "?";
-        } else {
-            StringBuilder b = new StringBuilder();
-            b.append(featuresReply.getDatapathId());
-            if(featuresReply.getVersion().compareTo(OFVersion.OF_13) >= 0) {
-                b.append("(").append(featuresReply.getAuxiliaryId()).append(")");
-            }
-            dpidString = b.toString();
-        }
-        return String.format("[%s from %s]", dpidString, channelString );
-    }
-
-    /**
-     * Update the channels state. Only called from the state machine.
-     * @param state
-     * @throws IOException
-     */
-    private void setState(OFChannelState state) throws IOException {
-        this.state = state;
-        state.logState();
-        state.enterState();
-    }
-
-    /**
-     * Send a features request message to the switch using the handshake
-     * transactions ids.
-     * @throws IOException
-     */
-    private void sendFeaturesRequest() throws IOException {
-        // Send initial Features Request
-        OFFeaturesRequest m = factory.buildFeaturesRequest()
-                .setXid(handshakeTransactionIds--)
-                .build();
-        channel.write(Collections.singletonList(m));
-    }
-
-    /**
-     * Send a hello message to the switch using the handshake transactions ids.
-     * @throws IOException
-     */
-    private void sendHelloMessage() throws IOException {
-        // Send initial hello message
-        // FIXME:LOJI: Haven't negotiated version yet, assume 1.3
-        OFHello.Builder builder = factory.buildHello()
-                .setXid(handshakeTransactionIds--);
-        // FIXME: Need to add code here to set the version bitmap hello element
-        OFHello m = builder.build();
-        channel.write(Collections.singletonList(m));
-        log.debug("Send hello: {}", m);
-    }
-
-    private void sendEchoRequest() {
-        OFEchoRequest request = factory.buildEchoRequest()
-                .setXid(handshakeTransactionIds--)
-                .build();
-        channel.write(Collections.singletonList(request));
-    }
-
-    private void sendEchoReply(OFEchoRequest request) {
-        OFEchoReply reply = factory.buildEchoReply()
-                .setXid(request.getXid())
-                .setData(request.getData())
-                .build();
-        channel.write(Collections.singletonList(reply));
-    }
-
-    OFChannelState getStateForTesting() {
-        return state;
-    }
-
-    IOFConnectionBackend getConnectionForTesting() {
-        return connection;
-    }
-
-    ChannelPipeline getPipelineForTesting() {
-        return this.pipeline;
-    }
+	private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
+
+	private final ChannelPipeline pipeline;
+	private final INewOFConnectionListener newConnectionListener;
+	private final SwitchManagerCounters counters;
+	private Channel channel;
+	private final Timer timer;
+	private volatile OFChannelState state;
+	private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
+	private OFFeaturesReply featuresReply;
+	private volatile OFConnection connection;
+	private final IDebugCounterService debugCounters;
+
+	/** transaction Ids to use during handshake. Since only one thread
+	 * calls into the OFChannelHandler we don't need atomic.
+	 * We will count down
+	 */
+	private long handshakeTransactionIds = 0x00FFFFFFFFL;
+
+
+	/**
+	 * Default implementation for message handlers in any OFChannelState.
+	 *
+	 * Individual states must override these if they want a behavior
+	 * that differs from the default.
+	 */
+	public abstract class OFChannelState {
+
+		void processOFHello(OFHello m)
+				throws IOException {
+			// we only expect hello in the WAIT_HELLO state
+			illegalMessageReceived(m);
+		}
+
+		void processOFEchoRequest(OFEchoRequest m)
+				throws IOException {
+			sendEchoReply(m);
+		}
+
+		void processOFEchoReply(OFEchoReply m)
+				throws IOException {
+			// do nothing
+		}
+
+		void processOFError(OFErrorMsg m) {
+			logErrorDisconnect(m);
+		}
+
+		void processOFExperimenter(OFExperimenter m) {
+			unhandledMessageReceived(m);
+		}
+
+		void processOFFeaturesReply(OFFeaturesReply  m)
+				throws IOException {
+			// we only expect features reply in the WAIT_FEATURES_REPLY state
+			illegalMessageReceived(m);
+		}
+
+		private final boolean channelHandshakeComplete;
+
+		OFChannelState(boolean handshakeComplete) {
+			this.channelHandshakeComplete = handshakeComplete;
+		}
+
+		void logState() {
+			log.debug("{} OFConnection Handshake - enter state {}",
+					getConnectionInfoString(), this.getClass().getSimpleName());
+		}
+
+		/** enter this state. Can initialize the handler, send
+		 *  the necessary messages, etc.
+		 * @throws IOException
+		 */
+		void enterState() throws IOException{
+			// Do Nothing
+		}
+
+		/**
+		 * Get a string specifying the switch connection, state, and
+		 * message received. To be used as message for SwitchStateException
+		 * or log messages
+		 * @param h The channel handler (to get switch information_
+		 * @param m The OFMessage that has just been received
+		 * @param details A string giving more details about the exact nature
+		 * of the problem.
+		 * @return
+		 */
+		// needs to be protected because enum members are acutally subclasses
+		protected String getSwitchStateMessage(OFMessage m,
+				String details) {
+			return String.format("Switch: [%s], State: [%s], received: [%s]"
+					+ ", details: %s",
+					getConnectionInfoString(),
+					this.toString(),
+					m.getType().toString(),
+					details);
+		}
+
+		/**
+		 * We have an OFMessage we didn't expect given the current state and
+		 * we want to treat this as an error.
+		 * We currently throw an exception that will terminate the connection
+		 * However, we could be more forgiving
+		 * @param h the channel handler that received the message
+		 * @param m the message
+		 * @throws SwitchStateExeption we always through the execption
+		 */
+		// needs to be protected because enum members are acutally subclasses
+		protected void illegalMessageReceived(OFMessage m) {
+			String msg = getSwitchStateMessage(m,
+					"Switch should never send this message in the current state");
+			throw new SwitchStateException(msg);
+
+		}
+
+		/**
+		 * We have an OFMessage we didn't expect given the current state and
+		 * we want to ignore the message
+		 * @param h the channel handler the received the message
+		 * @param m the message
+		 */
+		protected void unhandledMessageReceived(OFMessage m) {
+			counters.unhandledMessage.increment();
+			if (log.isDebugEnabled()) {
+				String msg = getSwitchStateMessage(m,
+						"Ignoring unexpected message");
+				log.debug(msg);
+			}
+		}
+
+		/**
+		 * Log an OpenFlow error message from a switch
+		 * @param sw The switch that sent the error
+		 * @param error The error message
+		 */
+		@LogMessageDoc(level="ERROR",
+				message="Error {error type} {error code} from {switch} " +
+						"in state {state}",
+						explanation="The switch responded with an unexpected error" +
+								"to an OpenFlow message from the controller",
+								recommendation="This could indicate improper network operation. " +
+										"If the problem persists restarting the switch and " +
+										"controller may help."
+				)
+		protected void logError(OFErrorMsg error) {
+			log.error("{} from switch {} in state {}",
+					new Object[] {
+					error.toString(),
+					getConnectionInfoString(),
+					this.toString()});
+		}
+
+		/**
+		 * Log an OpenFlow error message from a switch and disconnect the
+		 * channel
+		 * @param sw The switch that sent the error
+		 * @param error The error message
+		 */
+		protected void logErrorDisconnect(OFErrorMsg error) {
+			logError(error);
+			channel.disconnect();
+		}
+
+		/**
+		 * Process an OF message received on the channel and
+		 * update state accordingly.
+		 *
+		 * The main "event" of the state machine. Process the received message,
+		 * send follow up message if required and update state if required.
+		 *
+		 * Switches on the message type and calls more specific event handlers
+		 * for each individual OF message type. If we receive a message that
+		 * is supposed to be sent from a controller to a switch we throw
+		 * a SwitchStateExeption.
+		 *
+		 * The more specific handlers can also throw SwitchStateExceptions
+		 *
+		 * @param h The OFChannelHandler that received the message
+		 * @param m The message we received.
+		 * @throws SwitchStateException
+		 * @throws IOException
+		 */
+		void processOFMessage(OFMessage m)
+				throws IOException {
+			// Handle Channel Handshake
+			if (!state.channelHandshakeComplete) {
+				switch(m.getType()) {
+				case HELLO:
+					processOFHello((OFHello)m);
+					break;
+				case ERROR:
+					processOFError((OFErrorMsg)m);
+					break;
+				case FEATURES_REPLY:
+					processOFFeaturesReply((OFFeaturesReply)m);
+					break;
+				case EXPERIMENTER:
+					processOFExperimenter((OFExperimenter)m);
+					break;
+				default:
+					illegalMessageReceived(m);
+					break;
+				}
+			}
+			else{
+				switch(m.getType()){
+				// Always handle echos at the channel level!
+				// Echos should only be sent in the complete.
+				case ECHO_REPLY:
+					processOFEchoReply((OFEchoReply)m);
+					break;
+				case ECHO_REQUEST:
+					processOFEchoRequest((OFEchoRequest)m);
+					break;
+					// Send to SwitchManager and thus higher orders of control
+				default:
+					sendMessageToConnection(m);
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Initial state before channel is connected.
+	 */
+	class InitState extends OFChannelState {
+
+		InitState() {
+			super(false);
+		}
+	}
+
+	/**
+	 * We send a HELLO to the switch and wait for a reply.
+	 * Once we receive the reply we send an OFFeaturesRequest
+	 * Next state is WaitFeaturesReplyState
+	 */
+	class WaitHelloState extends OFChannelState {
+
+		WaitHelloState() {
+			super(false);
+		}
+
+		@Override
+		void processOFHello(OFHello m) throws IOException {
+			OFVersion version = m.getVersion();
+			factory = OFFactories.getFactory(version);
+			OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class);
+			decoder.setVersion(version);
+			setState(new WaitFeaturesReplyState());
+		}
+
+		@Override
+		void enterState() throws IOException {
+			sendHelloMessage();
+		}
+	}
+
+	/**
+	 * We are waiting for a features reply message. Once we receive it
+	 * we send capture the features reply.
+	 * Next state is CompleteState
+	 */
+	class WaitFeaturesReplyState extends OFChannelState{
+
+		WaitFeaturesReplyState() {
+			super(false);
+		}
+		@Override
+		void processOFFeaturesReply(OFFeaturesReply  m)
+				throws IOException {
+			featuresReply = m;
+
+			// Mark handshake as completed
+			setState(new CompleteState());
+
+		}
+		@Override
+		void enterState() throws IOException {
+			sendFeaturesRequest();
+		}
+	};
+
+	/**
+	 * This state denotes that the channel handshaking is complete.
+	 * An OF connection is generated and passed to the switch manager
+	 * for handling.
+	 */
+	class CompleteState extends OFChannelState{
+
+		CompleteState() {
+			super(true);
+		}
+
+		@Override
+		void enterState() throws IOException{
+
+			setSwitchHandshakeTimeout();
+
+			// Handle non 1.3 connections
+			if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){
+				connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, OFAuxId.MAIN, debugCounters, timer);
+			}
+			// Handle 1.3 connections
+			else{
+				connection = new OFConnection(featuresReply.getDatapathId(), factory, channel, featuresReply.getAuxiliaryId(), debugCounters, timer);
+
+				// If this is an aux connection, we set a longer echo idle time
+				if (!featuresReply.getAuxiliaryId().equals(OFAuxId.MAIN)) {
+					setAuxChannelIdle();
+				}
+			}
+			// Notify the connection broker
+			notifyConnectionOpened(connection);
+
+		}
+	};
+
+	/**
+	 * Creates a handler for interacting with the switch channel
+	 *
+	 * @param controller
+	 *            the controller
+	 * @param newConnectionListener
+	 *            the class that listens for new OF connections (switchManager)
+	 * @param pipeline
+	 *            the channel pipeline
+	 * @param threadPool
+	 *            the thread pool
+	 * @param idleTimer
+	 *            the hash wheeled timer used to send idle messages (echo).
+	 *            passed to constructor to modify in case of aux connection.
+	 * @param debugCounters
+	 */
+	OFChannelHandler(@Nonnull IOFSwitchManager switchManager,
+			@Nonnull INewOFConnectionListener newConnectionListener,
+			@Nonnull ChannelPipeline pipeline,
+			@Nonnull IDebugCounterService debugCounters,
+			@Nonnull Timer timer) {
+
+		Preconditions.checkNotNull(switchManager, "switchManager");
+		Preconditions.checkNotNull(newConnectionListener, "connectionOpenedListener");
+		Preconditions.checkNotNull(pipeline, "pipeline");
+		Preconditions.checkNotNull(timer, "timer");
+		Preconditions.checkNotNull(debugCounters, "debugCounters");
+
+		this.pipeline = pipeline;
+		this.debugCounters = debugCounters;
+		this.newConnectionListener = newConnectionListener;
+		this.counters = switchManager.getCounters();
+		this.state = new InitState();
+		this.timer = timer;
+
+		log.debug("constructor on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this)));
+	}
+
+	/**
+	 * Determines if the entire switch handshake is complete (channel+switch).
+	 * If the channel handshake is complete the call is forwarded to the
+	 * connection listener/switch manager to be handled by the appropriate
+	 * switch handshake handler.
+	 *
+	 * @return whether or not complete switch handshake is complete
+	 */
+	public boolean isSwitchHandshakeComplete() {
+		if (this.state.channelHandshakeComplete) {
+			return connection.getListener().isSwitchHandshakeComplete(connection);
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Notifies the channel listener that we have a valid baseline connection
+	 */
+	private final void notifyConnectionOpened(OFConnection connection){
+		this.connection = connection;
+		this.newConnectionListener.connectionOpened(connection, featuresReply);
+	}
+
+	/**
+	 * Notifies the channel listener that we our connection has been closed
+	 */
+	private final void notifyConnectionClosed(OFConnection connection){
+		connection.getListener().connectionClosed(connection);
+	}
+
+	/**
+	 * Notifies the channel listener that we have a valid baseline connection
+	 */
+	private final void sendMessageToConnection(OFMessage m) {
+		connection.messageReceived(m);
+	}
+
+	@Override
+	@LogMessageDoc(message="New switch connection from {ip address}",
+	explanation="A new switch has connected from the " +
+			"specified IP address")
+	public void channelConnected(ChannelHandlerContext ctx,
+			ChannelStateEvent e) throws Exception {
+		log.debug("channelConnected on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this)));
+		counters.switchConnected.increment();
+		channel = e.getChannel();
+		log.info("New switch connection from {}",
+				channel.getRemoteAddress());
+		setState(new WaitHelloState());
+	}
+
+	@Override
+	@LogMessageDoc(message="Disconnected switch {switch information}",
+	explanation="The specified switch has disconnected.")
+	public void channelDisconnected(ChannelHandlerContext ctx,
+			ChannelStateEvent e) throws Exception {
+		// Only handle cleanup connection is even known
+		if(this.connection != null){
+			// Alert the connection object that the channel has been disconnected
+			this.connection.disconnected();
+			// Punt the cleanup to the Switch Manager
+			notifyConnectionClosed(this.connection);
+		}
+		log.info("[{}] Disconnected connection", getConnectionInfoString());
+	}
+
+	@Override
+	@LogMessageDocs({
+		@LogMessageDoc(level="ERROR",
+				message="Disconnecting switch {switch} due to read timeout",
+				explanation="The connected switch has failed to send any " +
+						"messages or respond to echo requests",
+						recommendation=LogMessageDoc.CHECK_SWITCH),
+						@LogMessageDoc(level="ERROR",
+						message="Disconnecting switch {switch}: failed to " +
+								"complete handshake",
+								explanation="The switch did not respond correctly " +
+										"to handshake messages",
+										recommendation=LogMessageDoc.CHECK_SWITCH),
+										@LogMessageDoc(level="ERROR",
+										message="Disconnecting switch {switch} due to IO Error: {}",
+										explanation="There was an error communicating with the switch",
+										recommendation=LogMessageDoc.CHECK_SWITCH),
+										@LogMessageDoc(level="ERROR",
+										message="Disconnecting switch {switch} due to switch " +
+												"state error: {error}",
+												explanation="The switch sent an unexpected message",
+												recommendation=LogMessageDoc.CHECK_SWITCH),
+												@LogMessageDoc(level="ERROR",
+												message="Disconnecting switch {switch} due to " +
+														"message parse failure",
+														explanation="Could not parse a message from the switch",
+														recommendation=LogMessageDoc.CHECK_SWITCH),
+														@LogMessageDoc(level="ERROR",
+														message="Terminating controller due to storage exception",
+														explanation=Controller.ERROR_DATABASE,
+														recommendation=LogMessageDoc.CHECK_CONTROLLER),
+														@LogMessageDoc(level="ERROR",
+														message="Could not process message: queue full",
+														explanation="OpenFlow messages are arriving faster than " +
+																" the controller can process them.",
+																recommendation=LogMessageDoc.CHECK_CONTROLLER),
+																@LogMessageDoc(level="ERROR",
+																message="Error while processing message " +
+																		"from switch {switch} {cause}",
+																		explanation="An error occurred processing the switch message",
+																		recommendation=LogMessageDoc.GENERIC_ACTION)
+	})
+	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
+			throws Exception {
+		if (e.getCause() instanceof ReadTimeoutException) {
+
+			if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
+				log.error("Disconnecting switch {} due to read timeout on main cxn.",
+						getConnectionInfoString());
+				ctx.getChannel().close();
+			} else {
+				if (featuresReply.getAuxiliaryId().equals(OFAuxId.MAIN)) {
+					log.error("Disconnecting switch {} due to read timeout on main cxn.",
+							getConnectionInfoString());
+					ctx.getChannel().close();
+				} else {
+					// We only don't disconnect on aux connections
+					log.warn("Switch {} encountered read timeout on aux cxn.",
+							getConnectionInfoString());
+				}
+			}
+			// Increment counters
+			counters.switchDisconnectReadTimeout.increment();
+
+		} else if (e.getCause() instanceof HandshakeTimeoutException) {
+			log.error("Disconnecting switch {}: failed to complete handshake. Channel handshake complete : {}",
+					getConnectionInfoString(),
+					this.state.channelHandshakeComplete);
+			counters.switchDisconnectHandshakeTimeout.increment();
+			ctx.getChannel().close();
+		} else if (e.getCause() instanceof ClosedChannelException) {
+			log.debug("Channel for sw {} already closed", getConnectionInfoString());
+		} else if (e.getCause() instanceof IOException) {
+			log.error("Disconnecting switch {} due to IO Error: {}",
+					getConnectionInfoString(), e.getCause().getMessage());
+			if (log.isDebugEnabled()) {
+				// still print stack trace if debug is enabled
+				log.debug("StackTrace for previous Exception: ", e.getCause());
+			}
+			counters.switchDisconnectIOError.increment();
+			ctx.getChannel().close();
+		} else if (e.getCause() instanceof SwitchStateException) {
+			log.error("Disconnecting switch {} due to switch state error: {}",
+					getConnectionInfoString(), e.getCause().getMessage());
+			if (log.isDebugEnabled()) {
+				// still print stack trace if debug is enabled
+				log.debug("StackTrace for previous Exception: ", e.getCause());
+			}
+			counters.switchDisconnectSwitchStateException.increment();
+			ctx.getChannel().close();
+		} else if (e.getCause() instanceof OFAuxException) {
+			log.error("Disconnecting switch {} due to OF Aux error: {}",
+					getConnectionInfoString(), e.getCause().getMessage());
+			if (log.isDebugEnabled()) {
+				// still print stack trace if debug is enabled
+				log.debug("StackTrace for previous Exception: ", e.getCause());
+			}
+			counters.switchDisconnectSwitchStateException.increment();
+			ctx.getChannel().close();
+		} else if (e.getCause() instanceof OFParseError) {
+			log.error("Disconnecting switch "
+					+ getConnectionInfoString() +
+					" due to message parse failure",
+					e.getCause());
+			counters.switchDisconnectParseError.increment();
+			ctx.getChannel().close();
+		} else if (e.getCause() instanceof RejectedExecutionException) {
+			log.warn("Could not process message: queue full");
+			counters.rejectedExecutionException.increment();
+		} else {
+			log.error("Error while processing message from switch "
+					+ getConnectionInfoString()
+					+ "state " + this.state, e.getCause());
+			counters.switchDisconnectOtherException.increment();
+			ctx.getChannel().close();
+		}
+	}
+
+	@Override
+	public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
+			throws Exception {
+
+		log.debug("channelIdle on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this)));
+		OFChannelHandler handler = ctx.getPipeline().get(OFChannelHandler.class);
+		handler.sendEchoRequest();
+	}
+
+	@Override
+	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
+			throws Exception {
+		if (e.getMessage() instanceof List) {
+			@SuppressWarnings("unchecked")
+			List<OFMessage> msglist = (List<OFMessage>)e.getMessage();
+			for (OFMessage ofm : msglist) {
+				try {
+					// Do the actual packet processing
+					state.processOFMessage(ofm);
+				}
+				catch (Exception ex) {
+					// We are the last handler in the stream, so run the
+					// exception through the channel again by passing in
+					// ctx.getChannel().
+					Channels.fireExceptionCaught(ctx.getChannel(), ex);
+				}
+			}
+		}
+		else {
+			Channels.fireExceptionCaught(ctx.getChannel(),
+					new AssertionError("Message received from channel is not a list"));
+		}
+	}
+
+	/**
+	 * Sets the channel pipeline's idle (Echo) timeouts to a longer interval.
+	 * This is specifically for aux channels.
+	 */
+	private void setAuxChannelIdle() {
+
+		IdleStateHandler idleHandler = new IdleStateHandler(
+				this.timer,
+				PipelineIdleReadTimeout.AUX,
+				PipelineIdleWriteTimeout.AUX,
+				0);
+		pipeline.replace(PipelineHandler.MAIN_IDLE,
+				PipelineHandler.AUX_IDLE,
+				idleHandler);
+	}
+
+	/**
+	 * Sets the channel pipeline's handshake timeout to a more appropriate value
+	 * for the remaining part of the switch handshake.
+	 */
+	private void setSwitchHandshakeTimeout() {
+
+		HandshakeTimeoutHandler handler = new HandshakeTimeoutHandler(
+				this,
+				this.timer,
+				PipelineHandshakeTimeout.SWITCH);
+
+		pipeline.replace(PipelineHandler.CHANNEL_HANDSHAKE_TIMEOUT,
+				PipelineHandler.SWITCH_HANDSHAKE_TIMEOUT, handler);
+	}
+
+	/**
+	 * Return a string describing this switch based on the already available
+	 * information (DPID and/or remote socket)
+	 * @return
+	 */
+	private String getConnectionInfoString() {
+
+		String channelString;
+		if (channel == null || channel.getRemoteAddress() == null) {
+			channelString = "?";
+		} else {
+			channelString = channel.getRemoteAddress().toString();
+			if(channelString.startsWith("/"))
+				channelString = channelString.substring(1);
+		}
+		String dpidString;
+		if (featuresReply == null) {
+			dpidString = "?";
+		} else {
+			StringBuilder b = new StringBuilder();
+			b.append(featuresReply.getDatapathId());
+			if(featuresReply.getVersion().compareTo(OFVersion.OF_13) >= 0) {
+				b.append("(").append(featuresReply.getAuxiliaryId()).append(")");
+			}
+			dpidString = b.toString();
+		}
+		return String.format("[%s from %s]", dpidString, channelString );
+	}
+
+	/**
+	 * Update the channels state. Only called from the state machine.
+	 * @param state
+	 * @throws IOException
+	 */
+	private void setState(OFChannelState state) throws IOException {
+		this.state = state;
+		state.logState();
+		state.enterState();
+	}
+
+	/**
+	 * Send a features request message to the switch using the handshake
+	 * transactions ids.
+	 * @throws IOException
+	 */
+	private void sendFeaturesRequest() throws IOException {
+		// Send initial Features Request
+		OFFeaturesRequest m = factory.buildFeaturesRequest()
+				.setXid(handshakeTransactionIds--)
+				.build();
+		channel.write(Collections.singletonList(m));
+	}
+
+	/**
+	 * Send a hello message to the switch using the handshake transactions ids.
+	 * @throws IOException
+	 */
+	private void sendHelloMessage() throws IOException {
+		// Send initial hello message
+		// FIXME:LOJI: Haven't negotiated version yet, assume 1.3
+		OFHello.Builder builder = factory.buildHello()
+				.setXid(handshakeTransactionIds--);
+		// FIXME: Need to add code here to set the version bitmap hello element
+		OFHello m = builder.build();
+		channel.write(Collections.singletonList(m));
+		log.debug("Send hello: {}", m);
+	}
+
+	private void sendEchoRequest() {
+		OFEchoRequest request = factory.buildEchoRequest()
+				.setXid(handshakeTransactionIds--)
+				.build();
+		channel.write(Collections.singletonList(request));
+	}
+
+	private void sendEchoReply(OFEchoRequest request) {
+		OFEchoReply reply = factory.buildEchoReply()
+				.setXid(request.getXid())
+				.setData(request.getData())
+				.build();
+		channel.write(Collections.singletonList(reply));
+	}
+
+	OFChannelState getStateForTesting() {
+		return state;
+	}
+
+	IOFConnectionBackend getConnectionForTesting() {
+		return connection;
+	}
+
+	ChannelPipeline getPipelineForTesting() {
+		return this.pipeline;
+	}
 
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
index 5f15a1e23..5acd44059 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
@@ -7,13 +7,12 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.TimeUnit;
 
 import javax.annotation.Nonnull;
 
 import org.jboss.netty.util.Timer;
-import net.floodlightcontroller.core.GenTableMap;
+
 import net.floodlightcontroller.core.HARole;
 import net.floodlightcontroller.core.IOFConnection;
 import net.floodlightcontroller.core.IOFConnectionBackend;
@@ -25,16 +24,10 @@ import net.floodlightcontroller.core.SwitchDescription;
 import net.floodlightcontroller.core.annotations.LogMessageDoc;
 import net.floodlightcontroller.core.annotations.LogMessageDocs;
 import net.floodlightcontroller.core.internal.OFSwitchAppHandshakePlugin.PluginResultType;
+
 import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
 import org.projectfloodlight.openflow.protocol.OFBarrierReply;
 import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
-import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply;
-import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsRequest;
-import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsRequest;
-import org.projectfloodlight.openflow.protocol.OFBsnSetAuxCxnsReply;
-import org.projectfloodlight.openflow.protocol.OFBsnSetAuxCxnsRequest;
-import org.projectfloodlight.openflow.protocol.OFBsnSetL2TableRequest;
 import org.projectfloodlight.openflow.protocol.OFControllerRole;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFDescStatsRequest;
@@ -60,7 +53,6 @@ import org.projectfloodlight.openflow.protocol.OFRoleReply;
 import org.projectfloodlight.openflow.protocol.OFRoleRequest;
 import org.projectfloodlight.openflow.protocol.OFSetConfig;
 import org.projectfloodlight.openflow.protocol.OFStatsReply;
-import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
 import org.projectfloodlight.openflow.protocol.OFStatsRequestFlags;
 import org.projectfloodlight.openflow.protocol.OFStatsType;
 import org.projectfloodlight.openflow.protocol.OFType;
@@ -85,1815 +77,1490 @@ import com.google.common.collect.ImmutableSet;
  * @author Jason Parraga <jason.parraga@bigswitch.com>
  */
 public class OFSwitchHandshakeHandler implements IOFConnectionListener {
-    private static final Logger log = LoggerFactory.getLogger(OFSwitchHandshakeHandler.class);
-
-    private final IOFSwitchManager switchManager;
-    private final RoleManager roleManager;
-    private final IOFConnectionBackend mainConnection;
-    private final SwitchManagerCounters switchManagerCounters;
-    private IOFSwitchBackend sw;
-    private final Map<OFAuxId, IOFConnectionBackend> auxConnections;
-    private volatile OFSwitchHandshakeState state;
-    private RoleChanger roleChanger;
-    // Default to 1.3 - This is overwritten by the features reply
-    private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
-    private final OFFeaturesReply featuresReply;
-    private final Timer timer;
-
-    private final ArrayList<OFPortStatus> pendingPortStatusMsg;
-
-    /** transaction Ids to use during handshake. Since only one thread
-     * calls into the OFChannelHandler we don't need atomic.
-     * We will count down
-     */
-    private long handshakeTransactionIds = 0x00FFFFFFFFL;
-
-    /* Exponential backoff of master role assertion */
-    private final long MAX_ASSERT_TIME_INTERVAL_NS = TimeUnit.SECONDS.toNanos(120);
-    private final long DEFAULT_ROLE_TIMEOUT_NS = TimeUnit.SECONDS.toNanos(10);
-
-    protected OFPortDescStatsReply portDescStats;
-
-    /**
-     * When we remove a pending role request and set the role on the switch
-     * we use this enum to indicate how we arrived at the decision.
-     * @author gregor
-     */
-    private enum RoleRecvStatus {
-        /** We received a role reply message from the switch */
-        RECEIVED_REPLY,
-        /** The switch returned an error indicated that roles are not
-         * supported*/
-        UNSUPPORTED,
-        /** The request timed out */
-        NO_REPLY;
-    }
-    /**
-     * A utility class to handle role requests and replies for this channel.
-     * After a role request is submitted the role changer keeps track of the
-     * pending request, collects the reply (if any) and times out the request
-     * if necessary.
-     *
-     * To simplify role handling we only keep track of the /last/ pending
-     * role reply send to the switch. If multiple requests are pending and
-     * we receive replies for earlier requests we ignore them. However, this
-     * way of handling pending requests implies that we could wait forever if
-     * a new request is submitted before the timeout triggers. If necessary
-     * we could work around that though.
-     * @author gregor
-     */
-    private class RoleChanger {
-        // indicates that a request is currently pending
-        // needs to be volatile to allow correct double-check idiom
-        private volatile boolean requestPending;
-        // the transaction Id of the pending request
-        private long pendingXid;
-        // the role that's pending
-        private OFControllerRole pendingRole;
-        // system time in NS when we send the request
-        private long roleSubmitTimeNs;
-        // the timeout to use
-        private final long roleTimeoutNs;
-        private long lastAssertTimeNs;
-        private long assertTimeIntervalNs = TimeUnit.SECONDS.toNanos(1);
-
-        public RoleChanger(long roleTimeoutNs) {
-            this.roleTimeoutNs = roleTimeoutNs;
-            // System.nanoTime() may be negative -- prime the roleSubmitTime as
-            // "long ago in the past" to be robust against it.
-            this.roleSubmitTimeNs = System.nanoTime() - (2 * roleTimeoutNs);
-            this.lastAssertTimeNs = System.nanoTime() - (2 * assertTimeIntervalNs);
-            this.requestPending = false;
-            this.pendingXid = -1;
-            this.pendingRole = null;
-        }
-
-        /**
-         * Send Nicira role request message to the switch requesting the
-         * specified role.
-         *
-         * @param role role to request
-         */
-        private long sendNiciraRoleRequest(OFControllerRole role){
-
-            long xid;
-            // Construct the role request message
-            if(factory.getVersion().compareTo(OFVersion.OF_12) < 0) {
-                OFNiciraControllerRoleRequest.Builder builder =
-                        factory.buildNiciraControllerRoleRequest();
-                xid = factory.nextXid();
-                builder.setXid(xid);
-
-                OFNiciraControllerRole niciraRole = NiciraRoleUtils.ofRoleToNiciraRole(role);
-                builder.setRole(niciraRole);
-                OFNiciraControllerRoleRequest roleRequest = builder.build();
-                // Send it to the switch
-                mainConnection.write(roleRequest);
-            } else {
-                // send an OF 1.2+ role request
-                OFRoleRequest roleRequest = factory.buildRoleRequest()
-                        // we don't use the generation id scheme for now,
-                        // switch initializes to 0, we keep it at 0
-                        .setGenerationId(U64.of(0))
-                        .setRole(role)
-                        .build();
-                xid = roleRequest.getXid();
-                mainConnection.write(roleRequest);
-            }
-            return xid;
-        }
-
-        /**
-         * Send a role request for the given role only if no other role
-         * request is currently pending.
-         * @param role The role to send to the switch.
-         * @throws IOException
-         */
-        @LogMessageDoc(level="WARN",
-                message="Reasserting master role on switch {SWITCH}, " +
-                        "likely a configruation error with multiple masters",
-                explanation="The controller keeps getting permission error " +
-                        "from switch, likely due to switch connected to another " +
-                        "controller also in master mode",
-                        recommendation=LogMessageDoc.CHECK_SWITCH)
-        synchronized void sendRoleRequestIfNotPending(OFControllerRole role)
-                throws IOException {
-            long now = System.nanoTime();
-            if (now - lastAssertTimeNs < assertTimeIntervalNs) {
-                return;
-            }
-
-            lastAssertTimeNs = now;
-            if (assertTimeIntervalNs < MAX_ASSERT_TIME_INTERVAL_NS) { // 2 minutes max
-                assertTimeIntervalNs <<= 1;
-            } else if (role == OFControllerRole.ROLE_MASTER){
-                log.warn("Reasserting master role on switch {}, " +
-                        "likely a switch config error with multiple masters",
-                        role, sw);
-            }
-            if (!requestPending)
-                sendRoleRequest(role);
-            else
-                switchManagerCounters.roleNotResentBecauseRolePending.increment();
-        }
-
-        /**
-         * Send a role request with the given role to the switch.
-         *
-         * Send a role request with the given role to the switch and update
-         * the pending request and timestamp.
-         *
-         * @param role
-         * @throws IOException
-         */
-        synchronized void sendRoleRequest(OFControllerRole role) throws IOException {
-            /*
-             * There are three cases to consider for SUPPORTS_NX_ROLE:
-             *
-             * 1) unset. We have neither received a role reply from the
-             *    switch nor has a request timed out. Send a request.
-             * 2) TRUE: We've already send a request earlier and received
-             *    a reply. The switch supports role and we should send one.
-             * 3) FALSE: We have already send a role and received an error.
-             *    The switch does not support roles. Don't send a role request,
-             *    set the switch's role directly.
-             */
-            Boolean supportsNxRole = (Boolean)
-                    sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE);
-            if ((supportsNxRole != null) && !supportsNxRole) {
-                setSwitchRole(role, RoleRecvStatus.UNSUPPORTED);
-            } else {
-                pendingXid = sendNiciraRoleRequest(role);
-                pendingRole = role;
-                this.roleSubmitTimeNs = System.nanoTime();
-                requestPending = true;
-            }
-        }
-
-        /**
-         * Deliver a received role reply and set SWITCH_SUPPORTS_NX_ROLE.
-         *
-         * Check if a request is pending and if the received reply matches the
-         * the expected pending reply (we check both role and xid) we set
-         * the role for the switch/channel.
-         *
-         * If a request is pending but doesn't match the reply we ignore it.
-         *
-         * If no request is pending we disconnect.
-         *
-         * @param xid
-         * @param role
-         * @throws SwitchStateException if no request is pending
-         */
-        synchronized void deliverRoleReply(long xid, OFControllerRole role) {
-            if (!requestPending) {
-                // Maybe don't disconnect if the role reply we received is
-                // for the same role we are already in.
-                String msg = String.format("Switch: [%s], State: [%s], "
-                                + "received unexpected RoleReply[%s]. "
-                                + "No roles are pending",
-                                OFSwitchHandshakeHandler.this.getSwitchInfoString(),
-                                OFSwitchHandshakeHandler.this.state.toString(),
-                                role);
-                throw new SwitchStateException(msg);
-            }
-
-            if (pendingXid == xid && pendingRole == role) {
-                log.debug("[{}] Received role reply message setting role to {}",
-                          getDpid(), role);
-                switchManagerCounters.roleReplyReceived.increment();
-                setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY);
-            } else {
-                log.debug("[{}] Received stale or unexpected role reply " +
-                          "{}, xid={}. Ignoring. " +
-                          "Waiting for {}, xid={}",
-                          new Object[] { getDpid(), role, xid,
-                                         pendingRole, pendingXid });
-            }
-        }
-
-        /**
-         * Called if we receive an  error message. If the xid matches the
-         * pending request we handle it otherwise we ignore it. We also
-         * set SWITCH_SUPPORTS_NX_ROLE to false.
-         *
-         * Note: since we only keep the last pending request we might get
-         * error messages for earlier role requests that we won't be able
-         * to handle
-         * @param xid
-         * @return true if the error was handled by us, false otherwise
-         * @throws SwitchStateException if the error was for the pending
-         * role request but was unexpected
-         */
-        synchronized boolean deliverError(OFErrorMsg error) {
-            if (!requestPending)
-                return false;
-
-            if (pendingXid == error.getXid()) {
-                if (error.getErrType() == OFErrorType.BAD_REQUEST) {
-                    switchManagerCounters.roleReplyErrorUnsupported.increment();
-                    setSwitchRole(pendingRole, RoleRecvStatus.UNSUPPORTED);
-                } else {
-                    // TODO: Is this the right thing to do if we receive
-                    // some other error besides a bad request error?
-                    // Presumably that means the switch did actually
-                    // understand the role request message, but there
-                    // was some other error from processing the message.
-                    // OF 1.2 specifies a ROLE_REQUEST_FAILED
-                    // error code, but it doesn't look like the Nicira
-                    // role request has that. Should check OVS source
-                    // code to see if it's possible for any other errors
-                    // to be returned.
-                    // If we received an error the switch is not
-                    // in the correct role, so we need to disconnect it.
-                    // We could also resend the request but then we need to
-                    // check if there are other pending request in which
-                    // case we shouldn't resend. If we do resend we need
-                    // to make sure that the switch eventually accepts one
-                    // of our requests or disconnect the switch. This feels
-                    // cumbersome.
-                    String msg = String.format("Switch: [%s], State: [%s], "
-                                    + "Unexpected error %s in respone to our "
-                                    + "role request for %s.",
-                                    OFSwitchHandshakeHandler.this.getSwitchInfoString(),
-                                    OFSwitchHandshakeHandler.this.state.toString(),
-                                    error.toString(),
-                                    pendingRole);
-                    throw new SwitchStateException(msg);
-                }
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * Check if a pending role request has timed out.
-         */
-        void checkTimeout() {
-            if (!requestPending)
-                return;
-            synchronized(this) {
-                if (!requestPending)
-                    return;
-                long now = System.nanoTime();
-                if (now - this.roleSubmitTimeNs > roleTimeoutNs) {
-                    // timeout triggered.
-                    switchManagerCounters.roleReplyTimeout.increment();
-                    setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY);
-                }
-            }
-        }
-
-        /**
-         * Set the role for this switch / channel.
-         *
-         * If the status indicates that we received a reply we set the role.
-         * If the status indicates otherwise we disconnect the switch if
-         * the role is SLAVE.
-         *
-         * "Setting a role" means setting the appropriate ChannelState,
-         * setting the flags on the switch and
-         * notifying Controller.java about new role of the switch
-         *
-         * @param role The role to set.
-         * @param status How we derived at the decision to set this status.
-         */
-        synchronized private void setSwitchRole(OFControllerRole role, RoleRecvStatus status) {
-            requestPending = false;
-            if (status == RoleRecvStatus.RECEIVED_REPLY)
-                sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
-            else
-                sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
-            sw.setControllerRole(role);
-
-            if (role != OFControllerRole.ROLE_SLAVE) {
-                OFSwitchHandshakeHandler.this.setState(new MasterState());
-            } else {
-                if (status != RoleRecvStatus.RECEIVED_REPLY) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Disconnecting switch {}. Doesn't support role"
-                              + "({}) request and controller is now SLAVE",
-                              getSwitchInfoString(), status);
-                    }
-                    // the disconnect will trigger a switch removed to
-                    // controller so no need to signal anything else
-                    sw.disconnect();
-                } else {
-                    OFSwitchHandshakeHandler.this.setState(new SlaveState());
-                }
-            }
-        }
-    }
-
-    /**
-     * Default implementation for message handlers in any state.
-     *
-     * Individual states must override these if they want a behavior
-     * that differs from the default.
-     *
-     * In general, these handlers simply ignore the message and do
-     * nothing.
-     *
-     * There are some exceptions though, since some messages really
-     * are handled the same way in every state (e.g., ECHO_REQUST) or
-     * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY
-     */
-    public abstract class OFSwitchHandshakeState {
-
-        void processOFBarrierReply(OFBarrierReply m) {
-            // do nothing
-        }
-
-        void processOFError(OFErrorMsg m) {
-            logErrorDisconnect(m);
-        }
-
-        void processOFFlowRemoved(OFFlowRemoved m) {
-            unhandledMessageReceived(m);
-        }
-
-        void processOFGetConfigReply(OFGetConfigReply m) {
-            // we only expect config replies in the WAIT_CONFIG_REPLY state
-            // TODO: might use two different strategies depending on whether
-            // we got a miss length of 64k or not.
-            illegalMessageReceived(m);
-        }
-
-        void processOFPacketIn(OFPacketIn m) {
-            unhandledMessageReceived(m);
-        }
-
-        // By default add port status messages to a pending list
-        void processOFPortStatus(OFPortStatus m) {
-            pendingPortStatusMsg.add(m);
-        }
-
-        void processOFQueueGetConfigReply(OFQueueGetConfigReply m) {
-            unhandledMessageReceived(m);
-        }
-
-        void processOFStatsReply(OFStatsReply m) {
-            switch(m.getStatsType()) {
-                case PORT_DESC:
-                    processPortDescStatsReply((OFPortDescStatsReply) m);
-                    break;
-                default:
-                    unhandledMessageReceived(m);
-            }
-        }
-
-        void processOFExperimenter(OFExperimenter m) {
-            if (m instanceof OFBsnControllerConnectionsReply) {
-                OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
-                handleControllerConnectionMessage(reply);
-            } else {
-                unhandledMessageReceived(m);
-            }
-        }
-
-        void processPortDescStatsReply(OFPortDescStatsReply m) {
-            unhandledMessageReceived(m);
-        }
-
-        void processOFRoleReply(OFRoleReply m) {
-            unhandledMessageReceived(m);
-        }
-
-        private final boolean handshakeComplete;
-        OFSwitchHandshakeState(boolean handshakeComplete) {
-            this.handshakeComplete = handshakeComplete;
-        }
-
-        void logState() {
-            if(log.isDebugEnabled())
-                log.debug("[{}] - Switch Handshake - enter state {}", mainConnection.getDatapathId(), this.getClass().getSimpleName());
-        }
-
-        /** enter this state. Can initialize the handler, send
-         *  the necessary messages, etc.
-         */
-         void enterState(){
-         }
-
-        /**
-         * Is this a state in which the handshake has completed?
-         * @return true if the handshake is complete
-         */
-        public boolean isHandshakeComplete() {
-            return handshakeComplete;
-        }
-
-        /**
-         * Used to notify the WAIT OF AUX state that
-         * a new connection has been added
-         * @param connection
-         */
-        public void auxConnectionOpened(IOFConnectionBackend connection) {
-            // Should only be handled in wait of aux
-            log.debug("[{}] - Switch Handshake - unhandled aux connection event",
-                    getDpid());
-        }
-        /**
-         * Get a string specifying the switch connection, state, and
-         * message received. To be used as message for SwitchStateException
-         * or log messages
-         * @param h The channel handler (to get switch information_
-         * @param m The OFMessage that has just been received
-         * @param details A string giving more details about the exact nature
-         * of the problem.
-         * @return
-         */
-        // needs to be protected because enum members are acutally subclasses
-        protected String getSwitchStateMessage(OFMessage m,
-                                                      String details) {
-            return String.format("Switch: [%s], State: [%s], received: [%s]"
-                                 + ", details: %s",
-                                 getSwitchInfoString(),
-                                 this.toString(),
-                                 m.getType().toString(),
-                                 details);
-        }
-
-        /**
-         * We have an OFMessage we didn't expect given the current state and
-         * we want to treat this as an error.
-         * We currently throw an exception that will terminate the connection
-         * However, we could be more forgiving
-         * @param h the channel handler that received the message
-         * @param m the message
-         * @throws SwitchStateExeption we always through the execption
-         */
-        // needs to be protected because enum members are acutally subclasses
-        protected void illegalMessageReceived(OFMessage m) {
-            String msg = getSwitchStateMessage(m,
-                    "Switch should never send this message in the current state");
-            throw new SwitchStateException(msg);
-
-        }
-
-        /**
-         * We have an OFMessage we didn't expect given the current state and
-         * we want to ignore the message
-         * @param h the channel handler the received the message
-         * @param m the message
-         */
-        protected void unhandledMessageReceived(OFMessage m) {
-            switchManagerCounters.unhandledMessage.increment();
-            if (log.isDebugEnabled()) {
-                String msg = getSwitchStateMessage(m,
-                        "Ignoring unexpected message");
-                log.debug(msg);
-            }
-        }
-
-        /**
-         * Log an OpenFlow error message from a switch
-         * @param error The error message
-         */
-        @LogMessageDoc(level="ERROR",
-                message="Error {error type} {error code} from {switch} " +
-                        "in state {state}",
-                explanation="The switch responded with an unexpected error" +
-                        "to an OpenFlow message from the controller",
-                recommendation="This could indicate improper network operation. " +
-                        "If the problem persists restarting the switch and " +
-                        "controller may help."
-                )
-        protected void logError(OFErrorMsg error) {
-            log.error("{} from switch {} in state {}",
-                      new Object[] {
-                          error.toString(),
-                          getSwitchInfoString(),
-                          this.toString()});
-        }
-
-        /**
-         * Log an OpenFlow error message from a switch and disconnect the
-         * channel
-         * @param error The error message
-         */
-        protected void logErrorDisconnect(OFErrorMsg error) {
-            logError(error);
-            mainConnection.disconnect();
-        }
-
-        /**
-         * Extract the role from an OFVendor message.
-         *
-         * Extract the role from an OFVendor message if the message is a
-         * Nicira role reply. Otherwise return null.
-         *
-         * @param h The channel handler receiving the message
-         * @param vendorMessage The vendor message to parse.
-         * @return The role in the message if the message is a Nicira role
-         * reply, null otherwise.
-         */
-        protected OFControllerRole extractNiciraRoleReply(OFMessage vendorMessage) {
-            if (!(vendorMessage instanceof OFNiciraControllerRoleReply))
-                return null;
-            OFNiciraControllerRoleReply roleReply =
-                    (OFNiciraControllerRoleReply) vendorMessage;
-            return NiciraRoleUtils.niciraToOFRole(roleReply);
-        }
-
-        /**
-         * Handle a port status message.
-         *
-         * Handle a port status message by updating the port maps in the
-         * IOFSwitch instance and notifying Controller about the change so
-         * it can dispatch a switch update.
-         *
-         * @param h The OFChannelHhandler that received the message
-         * @param m The PortStatus message we received
-         * @param doNotify if true switch port changed events will be
-         * dispatched
-         */
-        protected void handlePortStatusMessage(OFPortStatus m,
-                                               boolean doNotify) {
-            if (sw == null) {
-                String msg = getSwitchStateMessage(m,
-                        "State machine error: switch is null. Should never " +
-                        "happen");
-                throw new SwitchStateException(msg);
-            }
-            Collection<PortChangeEvent> changes = sw.processOFPortStatus(m);
-            if (doNotify) {
-                for (PortChangeEvent ev: changes)
-                    switchManager.notifyPortChanged(sw, ev.port, ev.type);
-            }
-        }
-
-        protected void handleControllerConnectionMessage(OFBsnControllerConnectionsReply m) {
-            if (sw == null) {
-                String msg = getSwitchStateMessage(m,
-                        "State machine error: switch is null. Should never " +
-                        "happen");
-                throw new SwitchStateException(msg);
-            }
-            // Update switches
-            sw.updateControllerConnections(m);
-            // Notify role manager
-            roleManager.notifyControllerConnectionUpdate();
-        }
-
-
-        /**
-         * Process an OF message received on the channel and
-         * update state accordingly.
-         *
-         * The main "event" of the state machine. Process the received message,
-         * send follow up message if required and update state if required.
-         *
-         * Switches on the message type and calls more specific event handlers
-         * for each individual OF message type. If we receive a message that
-         * is supposed to be sent from a controller to a switch we throw
-         * a SwitchStateExeption.
-         *
-         * The more specific handlers can also throw SwitchStateExceptions
-         *
-         * @param h The OFChannelHandler that received the message
-         * @param m The message we received.
-         * @throws SwitchStateException
-         * @throws IOException
-         */
-        void processOFMessage(OFMessage m) {
-            roleChanger.checkTimeout();
-            switch(m.getType()) {
-                case BARRIER_REPLY:
-                    processOFBarrierReply((OFBarrierReply)m);
-                    break;
-                case ERROR:
-                    processOFError((OFErrorMsg)m);
-                    break;
-                case FLOW_REMOVED:
-                    processOFFlowRemoved((OFFlowRemoved)m);
-                    break;
-                case GET_CONFIG_REPLY:
-                    processOFGetConfigReply((OFGetConfigReply)m);
-                    break;
-                case PACKET_IN:
-                    processOFPacketIn((OFPacketIn)m);
-                    break;
-                case PORT_STATUS:
-                    processOFPortStatus((OFPortStatus)m);
-                    break;
-                case QUEUE_GET_CONFIG_REPLY:
-                    processOFQueueGetConfigReply((OFQueueGetConfigReply)m);
-                    break;
-                case STATS_REPLY:
-                    processOFStatsReply((OFStatsReply)m);
-                    break;
-                case ROLE_REPLY:
-                    processOFRoleReply((OFRoleReply)m);
-                    break;
-                case EXPERIMENTER:
-                    processOFExperimenter((OFExperimenter)m);
-                    break;
-                default:
-                    illegalMessageReceived(m);
-                    break;
-            }
-        }
-    }
-
-        /**
-         * Initial state before channel is connected. Should not handle any messages.
-         */
-          public class InitState extends OFSwitchHandshakeState {
-
-            InitState() {
-                super(false);
-            }
-
-            @Override
-            public void logState() {
-                log.debug("[{}] - Switch Handshake - Initiating from {}",
-                        getDpid(), mainConnection.getRemoteInetAddress());
-            }
-        }
-
-        /**
-         * We are waiting for a features reply message. Once we receive it
-         * we send a SetConfig request, barrier, and GetConfig request.
-         * Next stats is WAIT_CONFIG_REPLY or WAIT_SET_L2_TABLE_REPLY
-         */
-        public class WaitPortDescStatsReplyState extends OFSwitchHandshakeState {
-            WaitPortDescStatsReplyState() {
-                super(false);
-            }
-
-            @Override
-            void enterState(){
-                sendPortDescRequest();
-            }
-
-            @Override
-            void processPortDescStatsReply(OFPortDescStatsReply  m) {
-                portDescStats = m;
-
-                setState(new WaitConfigReplyState());
-            }
-
-            @Override
-            void processOFExperimenter(OFExperimenter m) {
-                unhandledMessageReceived(m);
-            }
-        }
-
-        public class WaitSetL2TableReplyState extends OFSwitchHandshakeState {
-
-            WaitSetL2TableReplyState() {
-                super(false);
-            }
-
-            @Override
-            void processOFExperimenter(OFExperimenter m) {
-                // TODO: actually parse the response
-                setState(new WaitConfigReplyState());
-            };
-
-            @Override
-            void processOFStatsReply(OFStatsReply  m) {
-                illegalMessageReceived(m);
-            }
-        }
-
-        /**
-         * We are waiting for a config reply message. Once we receive it
-         * we send a DescriptionStatsRequest to the switch.
-         * Next state: WAIT_DESCRIPTION_STAT_REPLY
-         */
-        public class WaitConfigReplyState extends OFSwitchHandshakeState {
-
-            WaitConfigReplyState() {
-                super(false);
-            }
-
-            @Override
-            @LogMessageDocs({
-                @LogMessageDoc(level="WARN",
-                        message="Config Reply from {switch} has " +
-                                "miss length set to {length}",
-                        explanation="The controller requires that the switch " +
-                                "use a miss length of 0xffff for correct " +
-                                "function",
-                        recommendation="Use a different switch to ensure " +
-                                "correct function")
-            })
-            void processOFGetConfigReply(OFGetConfigReply m) {
-                if (m.getMissSendLen() == 0xffff) {
-                    log.trace("Config Reply from switch {} confirms "
-                            + "miss length set to 0xffff",
-                            getSwitchInfoString());
-                } else {
-                    // FIXME: we can't really deal with switches that don't send
-                    // full packets. Shouldn't we drop the connection here?
-                    // FIXME: count??
-                    log.warn("Config Reply from switch {} has"
-                            + "miss length set to {}",
-                            getSwitchInfoString(),
-                            m.getMissSendLen());
-                }
-                setState(new WaitDescriptionStatReplyState());
-            }
-
-            @Override
-            void processOFStatsReply(OFStatsReply  m) {
-                illegalMessageReceived(m);
-            }
-
-            @Override
-            void processOFError(OFErrorMsg m) {
-                if ((m.getErrType() == OFErrorType.BAD_REQUEST) &&
-                        (((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.BAD_EXPERIMENTER)) {
-                    log.debug("Switch {} has multiple tables but does not " +
-                            "support L2 table extension",
-                            getSwitchInfoString());
-                    return;
-                }
-                logErrorDisconnect(m);
-            }
-
-            @Override
-            void enterState() {
-                sendHandshakeSetConfig();
-            }
-        }
-
-        /**
-         * We are waiting for a OFDescriptionStat message from the switch.
-         * Once we receive any stat message we try to parse it. If it's not
-         * a description stats message we disconnect. If its the expected
-         * description stats message, we:
-         *    - use the switch driver to bind the switch and get an IOFSwitch
-         *      instance, setup the switch instance
-         *    - setup the IOFSwitch instance
-         *    - add switch to FloodlightProvider and send the intial role
-         *      request to the switch.
-         *
-         * Next state: WaitOFAuxCxnsReplyState (if OF1.3), else
-         *     WaitInitialRoleState or WaitSwitchDriverSubHandshake
-         *
-         * All following states will have a h.sw instance!
-         */
-        public class WaitDescriptionStatReplyState extends OFSwitchHandshakeState{
-
-            WaitDescriptionStatReplyState() {
-                super(false);
-            }
-
-            @LogMessageDoc(message="Switch {switch info} bound to class " +
-                "{switch driver}, description {switch description}",
-                    explanation="The specified switch has been bound to " +
-                            "a switch driver based on the switch description" +
-                            "received from the switch")
-            @Override
-            void processOFStatsReply(OFStatsReply m) {
-                // Read description, if it has been updated
-                if (m.getStatsType() != OFStatsType.DESC) {
-                    illegalMessageReceived(m);
-                    return;
-                }
-
-                OFDescStatsReply descStatsReply = (OFDescStatsReply) m;
-                SwitchDescription description = new SwitchDescription(descStatsReply);
-                sw = switchManager.getOFSwitchInstance(mainConnection, description, factory, featuresReply.getDatapathId());
-                switchManager.switchAdded(sw);
-                // set switch information
-                // set features reply and channel first so we a DPID and
-                // channel info.
-                sw.setFeaturesReply(featuresReply);
-                if(portDescStats != null) {
-                    sw.setPortDescStats(portDescStats);
-                }
-
-                // Handle pending messages now that we have a sw object
-                handlePendingPortStatusMessages(description);
-
-                // Handle non OF 13 connections
-                if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){
-                    sw.startDriverHandshake();
-                    if (sw.isDriverHandshakeComplete()) {
-                        setState(new WaitAppHandshakeState());
-                    } else {
-                        setState(new WaitSwitchDriverSubHandshakeState());
-                    }
-                }
-                // Handle OF 1.3 MAIN Connection
-                else{
-                    setState(new WaitOFAuxCxnsReplyState());
-                }
-            }
-
-            void handlePendingPortStatusMessages(SwitchDescription description){
-                for (OFPortStatus ps: pendingPortStatusMsg)
-                    handlePortStatusMessage(ps, false);
-                pendingPortStatusMsg.clear();
-                log.info("Switch {} bound to class {}," +
-                        " description {}",
-                         new Object[] { sw, sw.getClass(),
-                                    description });
-            }
-
-            @Override
-            void enterState() {
-                sendHandshakeDescriptionStatsRequest();
-            }
-        }
-
-        /**
-         * We are waiting for an OFAuxCxnsReply message from the switch.
-         *  If the switch replies with a status of 0 it has approved of our request.
-         *  If the auxiliary connections haven't already connected we will
-         *  wait for them.
-         *
-         * Next state: WAIT_GENTABLE_DESC_STATS_REPLY (if OF1.3), else
-         *     WAIT_INITIAL_ROLE or WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
-         *
-         * All following states will have a h.sw instance!
-         */
-        public class WaitOFAuxCxnsReplyState extends OFSwitchHandshakeState {
-
-            // Default number of aux connections
-            int numAux = 0;
-
-            WaitOFAuxCxnsReplyState() {
-                super(false);
-            }
-
-            @Override
-            void processOFExperimenter(OFExperimenter m) {
-               if(m instanceof OFBsnSetAuxCxnsReply){
-                   OFBsnSetAuxCxnsReply auxReply = (OFBsnSetAuxCxnsReply) m;
-
-                   if(auxReply.getStatus() == 0){
-                       if(this.numAux != 0){
-                           // All aux connections havent arrived yet
-                           if(auxConnections.size() != this.numAux){
-                               // We do nothing and wait for connections...
-                           } else {
-                               // Looks like all the aux connections have already arrived
-                               gotoNextState();
-                           }
-                       }
-                       else {
-                           // We don't need any OF Aux Connections
-                           gotoNextState();
-                       }
-                   } else {
-                       String msg = String.format("Switch: [%s], HandshakeState: [%s], "
-                               + "received unexpected OF Aux Status [%s]. ",
-                               OFSwitchHandshakeHandler.this.getSwitchInfoString(),
-                               OFSwitchHandshakeHandler.this.state.toString(),
-                               String.valueOf(auxReply.getStatus()));
-                       throw new OFAuxException(msg);
-                   }
-               } else if(m instanceof OFBsnControllerConnectionsReply) {
-                   OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
-                   handleControllerConnectionMessage(reply);
-               }
-            }
-
-            @Override
-            public void auxConnectionOpened(IOFConnectionBackend auxConnection){
-                auxConnections.put(auxConnection.getAuxId(), auxConnection);
-                auxConnection.setListener(OFSwitchHandshakeHandler.this);
-
-                // Only handle success case
-                if(auxConnections.size() == this.numAux){
-                    if(log.isDebugEnabled()) {
-                        log.debug("[{}] - all {} required aux connections open. Proceeding",
-                                getDpid(), numAux);
-                    }
-                    gotoNextState();
-                } else {
-                    log.debug("[" + getDpid() + "] - {} / {} required aux connections open. Waiting for more connections. ",
-                            auxConnections.size(), numAux);
-                }
-            }
-
-            @Override
-            void processOFError(OFErrorMsg m) {
-                log.info("Received error on OF Aux handshake - switch does not support OF Aux: {}", m);
-                gotoNextState();
-            }
-
-            void gotoNextState(){
-                // Register any aux connections that have been receieved.
-                for (IOFConnectionBackend conn : auxConnections.values()) {
-                    sw.registerConnection(conn);
-                }
-                //TODO @Ryan but we should still add the main connection as one, right?
-                //sw.registerConnection(mainConnection); // don't think so bc the connection is already associated 
-                // with the ofswitch
-                setState(new WaitGentableDescStatsReplyState());
-            }
-
-            @Override
-            public void enterState() {
-                this.numAux = switchManager.getNumRequiredConnections();
-                sendOFAuxSetCxnsRequest(this.numAux);
-            }
-
-            @Override
-            void processOFPortStatus(OFPortStatus m) {
-                handlePortStatusMessage(m, false);
-            }
-        }
-
-        /**
-         * We have requested the GenTable mapping (OFBsnGenTableDescStatsRequest)
-         * and are waiting on the reply / replies (note: it is a multipart message).
-         * Once we're received all parts, we create a GenTableMapping object and
-         * set it in the switch.
-         *
-         * If we receive an error messsage corresponding to our request, we conclude
-         * that the switch doesn't support GenTables and leave the empty default
-         * mapping in the switch.
-         *
-         * Next state: WaitSwitchDriverSubHandshakeState() if a driver handshake is required
-         *     WaitAppHandshake else
-         */
-        public class WaitGentableDescStatsReplyState extends OFSwitchHandshakeState {
-
-            private final List<OFBsnGentableDescStatsReply> pendingGenTableDescStatsReplies;
-            private final long pendingRequestXid;
-
-            WaitGentableDescStatsReplyState() {
-                super(false);
-                pendingGenTableDescStatsReplies = new CopyOnWriteArrayList<>();
-                pendingRequestXid = sendHandshakeGenTableDescStatsRequest();
-            }
-
-            @Override
-            void processOFStatsReply(OFStatsReply m) {
-                // Read description, if it has been updated
-                if (!(m instanceof OFBsnGentableDescStatsReply)) {
-                    illegalMessageReceived(m);
-                    return;
-                }
-
-                OFBsnGentableDescStatsReply reply = (OFBsnGentableDescStatsReply) m;
-
-                pendingGenTableDescStatsReplies.add(reply);
-                if(reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
-                    // more replies to follow, stay in state
-                    return;
-                }
-
-                if(sw == null) {
-                    throw new IllegalArgumentException("Switch instance unknown at time of GenTableDescStatsReply");
-                }
-
-                GenTableMap genTableMap = GenTableMap.of(pendingGenTableDescStatsReplies);
-                if(log.isDebugEnabled())
-                    log.debug("[{}] Gen Tables: {}", sw.getId(), genTableMap);
-                sw.setGenTableMap(genTableMap);
-
-                gotoNextState();
-            }
-
-            public void gotoNextState() {
-                sw.startDriverHandshake();
-                if (sw.isDriverHandshakeComplete())
-                    setState(new WaitAppHandshakeState());
-                else
-                    setState(new WaitSwitchDriverSubHandshakeState());
-            }
-
-            @Override
-            void processOFError(OFErrorMsg m) {
-                if(m.getXid() == pendingRequestXid) {
-                    // let switch continue with an empty set of gentables
-                    log.info("Received error on GenTable handshake - switch does not support gentables: {}", m);
-                    gotoNextState();
-                } else {
-                    illegalMessageReceived(m);
-                }
-            }
-
-            @Override
-            void processOFPortStatus(OFPortStatus m) {
-                handlePortStatusMessage(m, false);
-            }
-        }
-
-        public class WaitSwitchDriverSubHandshakeState extends OFSwitchHandshakeState {
-
-            WaitSwitchDriverSubHandshakeState() {
-                super(false);
-            }
-
-            @Override
-            void processOFMessage(OFMessage m) {
-                // FIXME: other message to handle here?
-                sw.processDriverHandshakeMessage(m);
-                if (sw.isDriverHandshakeComplete()) {
-                    setState(new WaitAppHandshakeState());
-                }
-            }
-
-            @Override
-            void processOFPortStatus(OFPortStatus m) {
-                handlePortStatusMessage(m, false);
-            }
-        }
-
-    public class WaitAppHandshakeState extends OFSwitchHandshakeState {
-
-        private final Iterator<IAppHandshakePluginFactory> pluginIterator;
-        private OFSwitchAppHandshakePlugin plugin;
-
-        WaitAppHandshakeState() {
-            super(false);
-            this.pluginIterator = switchManager.getHandshakePlugins().iterator();
-        }
-
-        @Override
-        void processOFMessage(OFMessage m) {
-            if(m.getType() == OFType.PORT_STATUS){
-                OFPortStatus status = (OFPortStatus) m;
-                handlePortStatusMessage(status, false);
-            }
-            else if(plugin != null){
-                this.plugin.processOFMessage(m);
-            }
-            else{
-                super.processOFMessage(m);
-            }
-        }
-
-        /**
-         * Called by handshake plugins to signify that they have finished their
-         * sub handshake.
-         *
-         * @param result
-         *            the result of the sub handshake
-         */
-        void exitPlugin(PluginResult result) {
-
-            // Proceed
-            if (result.getResultType() == PluginResultType.CONTINUE) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}."
-                            + " Proceeding normally..",
-                            this.plugin.getClass().getSimpleName(), result);
-                }
-
-                enterNextPlugin();
-
-            // Stop
-            } else if (result.getResultType() == PluginResultType.DISCONNECT) {
-                log.error("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. "
-                        + "Disconnecting switch.",
-                        this.plugin.getClass().getSimpleName(), result);
-                mainConnection.disconnect();
-            } else if (result.getResultType() == PluginResultType.QUARANTINE) {
-                log.warn("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. "
-                        + "Putting switch into quarantine state.",
-                        this.plugin.getClass().getSimpleName(),
-                         result);
-                setState(new QuarantineState(result.getReason()));
-            }
-        }
-
-        @Override
-        public void enterState() {
-            enterNextPlugin();
-        }
-
-        /**
-         * Initialize the plugin and begin.
-         *
-         * @param plugin the of switch app handshake plugin
-         */
-        public void enterNextPlugin() {
-            if(this.pluginIterator.hasNext()){
-                this.plugin = pluginIterator.next().createPlugin();
-                this.plugin.init(this, sw, timer);
-                this.plugin.enterPlugin();
-            }
-            // No more plugins left...
-            else{
-                // Non OF 1.3
-                if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){
-                    setState(new WaitInitialRoleState());
-                } else {
-                    setState(new WaitControllerCxnsReplyState());
-                }
-            }
-        }
-
-        @Override
-        void processOFPortStatus(OFPortStatus m) {
-            handlePortStatusMessage(m, false);
-        }
-
-        OFSwitchAppHandshakePlugin getCurrentPlugin() {
-            return plugin;
-        }
-
-    }
-
-    /**
-     * Switch is in a quarantine state. Essentially the handshake is complete.
-     */
-    public class QuarantineState extends OFSwitchHandshakeState {
-
-        private final String quarantineReason;
-
-        QuarantineState(String reason) {
-            super(true);
-            this.quarantineReason = reason;
-        }
-
-        @Override
-        public void enterState() {
-            setSwitchStatus(SwitchStatus.QUARANTINED);
-        }
-
-        @Override
-        void processOFPortStatus(OFPortStatus m) {
-            handlePortStatusMessage(m, false);
-        }
-
-        public String getQuarantineReason() {
-            return this.quarantineReason;
-        }
-    }
-
-    public class WaitControllerCxnsReplyState extends OFSwitchHandshakeState {
-
-        WaitControllerCxnsReplyState() {
-            super(false);
-        }
-
-        @Override
-        void processOFExperimenter(OFExperimenter m) {
-            if(m instanceof OFBsnControllerConnectionsReply) {
-                OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
-                handleControllerConnectionMessage(reply);
-
-                setState(new WaitInitialRoleState());
-            } else {
-                unhandledMessageReceived(m);
-            }
-        }
-        
-        @Override
-        void processOFError(OFErrorMsg m) {
-        	// @Ryan Need to handle case where the switch is not a BSN switch
-            setState(new WaitInitialRoleState());
-        }
-
-        @Override
-        void processOFPortStatus(OFPortStatus m) {
-            handlePortStatusMessage(m, false);
-        }
-
-        @Override
-        public void enterState() {
-            // Write out request down
-            OFBsnControllerConnectionsRequest request = factory.buildBsnControllerConnectionsRequest()
-                    .build();
-            mainConnection.write(request);
-
-        }
-
-    }
-
-    /**
-     * We are waiting for the initial role reply message (or error indication)
-     * from the switch. Next State: MASTER or SLAVE
-     */
-        public class WaitInitialRoleState extends OFSwitchHandshakeState {
-
-            WaitInitialRoleState() {
-                super(false);
-            }
-
-            @Override
-            void processOFError(OFErrorMsg m) {
-                // role changer will ignore the error if it isn't for it
-                boolean didHandle = roleChanger.deliverError(m);
-                if (!didHandle) {
-                    logError(m);
-                }
-            }
-
-            @Override
-            void processOFExperimenter(OFExperimenter m) {
-                OFControllerRole role = extractNiciraRoleReply(m);
-                // If role == null it measn the message wasn't really a
-                // Nicira role reply. We ignore this case.
-                if (role != null) {
-                    roleChanger.deliverRoleReply(m.getXid(), role);
-                } else if(m instanceof OFBsnControllerConnectionsReply) {
-                    OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
-                    handleControllerConnectionMessage(reply);
-                } else {
-                    unhandledMessageReceived(m);
-                }
-            }
-
-            @Override
-            void processOFRoleReply(OFRoleReply m) {
-                roleChanger.deliverRoleReply(m.getXid(), m.getRole());
-            }
-
-            @Override
-            void processOFStatsReply(OFStatsReply m) {
-                illegalMessageReceived(m);
-            }
-
-            @Override
-            void processOFPortStatus(OFPortStatus m) {
-                handlePortStatusMessage(m, false);
-            }
-
-            @Override
-            void enterState(){
-                sendRoleRequest(roleManager.getOFControllerRole());
-            }
-        }
-
-        /**
-         * The switch is in MASTER role. We enter this state after a role
-         * reply from the switch is received (or the controller is MASTER
-         * and the switch doesn't support roles). The handshake is complete at
-         * this point. We only leave this state if the switch disconnects or
-         * if we send a role request for SLAVE /and/ receive the role reply for
-         * SLAVE.
-         */
-        public class MasterState extends OFSwitchHandshakeState {
-
-            MasterState() {
-                super(true);
-            }
-
-            @Override
-            void enterState() {
-                setSwitchStatus(SwitchStatus.MASTER);
-            }
-
-            @LogMessageDoc(level="WARN",
-                message="Received permission error from switch {} while" +
-                         "being master. Reasserting master role.",
-                explanation="The switch has denied an operation likely " +
-                         "indicating inconsistent controller roles",
-                recommendation="This situation can occurs transiently during role" +
-                 " changes. If, however, the condition persists or happens" +
-                 " frequently this indicates a role inconsistency. " +
-                 LogMessageDoc.CHECK_CONTROLLER )
-            @Override
-            void processOFError(OFErrorMsg m) {
-                // role changer will ignore the error if it isn't for it
-                boolean didHandle = roleChanger.deliverError(m);
-                if (didHandle)
-                    return;
-                if ((m.getErrType() == OFErrorType.BAD_REQUEST) &&
-                        (((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.EPERM)) {
-                    // We are the master controller and the switch returned
-                    // a permission error. This is a likely indicator that
-                    // the switch thinks we are slave. Reassert our
-                    // role
-                    // FIXME: this could be really bad during role transitions
-                    // if two controllers are master (even if its only for
-                    // a brief period). We might need to see if these errors
-                    // persist before we reassert
-                    switchManagerCounters.epermErrorWhileSwitchIsMaster.increment();
-                    log.warn("Received permission error from switch {} while" +
-                             "being master. Reasserting master role.",
-                             getSwitchInfoString());
-                    reassertRole(OFControllerRole.ROLE_MASTER);
-                }
-                else if ((m.getErrType() == OFErrorType.FLOW_MOD_FAILED) &&
-                        (((OFFlowModFailedErrorMsg)m).getCode() == OFFlowModFailedCode.ALL_TABLES_FULL)) {
-                    sw.setTableFull(true);
-                }
-                else {
-                    logError(m);
-                }
-                dispatchMessage(m);
-            }
-
-            @Override
-            void processOFExperimenter(OFExperimenter m) {
-                OFControllerRole role = extractNiciraRoleReply(m);
-                // If role == null it means the message wasn't really a
-                // Nicira role reply. We ignore just dispatch it to the
-                // OFMessage listenersa in this case.
-                if (role != null) {
-                    roleChanger.deliverRoleReply(m.getXid(), role);
-                } else if (m instanceof OFBsnControllerConnectionsReply){
-                    OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
-                    handleControllerConnectionMessage(reply);
-                } else {
-                    dispatchMessage(m);
-                }
-            }
-
-
-            @Override
-            void processOFRoleReply(OFRoleReply m) {
-                roleChanger.deliverRoleReply(m.getXid(), m.getRole());
-            }
-
-            @Override
-            void processOFPortStatus(OFPortStatus m) {
-                handlePortStatusMessage(m, true);
-            }
-
-            @Override
-            void processOFPacketIn(OFPacketIn m) {
-                dispatchMessage(m);
-            }
-
-            @Override
-            void processOFFlowRemoved(OFFlowRemoved m) {
-                dispatchMessage(m);
-            }
-        }
-
-        /**
-         * The switch is in SLAVE role. We enter this state after a role
-         * reply from the switch is received. The handshake is complete at
-         * this point. We only leave this state if the switch disconnects or
-         * if we send a role request for MASTER /and/ receive the role reply for
-         * MASTER.
-         * TODO: CURRENTLY, WE DO NOT DISPATCH ANY MESSAGE IN SLAVE.
-         */
-        public class SlaveState extends OFSwitchHandshakeState {
-
-            SlaveState() {
-                super(true);
-            }
-
-            @Override
-            void enterState() {
-                setSwitchStatus(SwitchStatus.SLAVE);
-            }
-
-            @Override
-            void processOFError(OFErrorMsg m) {
-                // role changer will ignore the error if it isn't for it
-                boolean didHandle = roleChanger.deliverError(m);
-                if (!didHandle) {
-                    logError(m);
-                }
-            }
-
-            @Override
-            void processOFStatsReply(OFStatsReply m) {
-            }
-
-            @Override
-            void processOFPortStatus(OFPortStatus m) {
-                handlePortStatusMessage(m, true);
-            }
-
-            @Override
-            void processOFExperimenter(OFExperimenter m) {
-                OFControllerRole role = extractNiciraRoleReply(m);
-                // If role == null it means the message wasn't really a
-                // Nicira role reply. We ignore it.
-                if (role != null) {
-                    roleChanger.deliverRoleReply(m.getXid(), role);
-                } else if (m instanceof OFBsnControllerConnectionsReply){
-                    OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
-                    handleControllerConnectionMessage(reply);
-                } else {
-                    unhandledMessageReceived(m);
-                }
-            }
-
-            @Override
-            void processOFRoleReply(OFRoleReply m) {
-                roleChanger.deliverRoleReply(m.getXid(), m.getRole());
-            }
-
-            @Override
-            @LogMessageDoc(level="WARN",
-                message="Received PacketIn from switch {} while" +
-                         "being slave. Reasserting slave role.",
-                explanation="The switch has receive a PacketIn despite being " +
-                         "in slave role indicating inconsistent controller roles",
-                recommendation="This situation can occurs transiently during role" +
-                         " changes. If, however, the condition persists or happens" +
-                         " frequently this indicates a role inconsistency. " +
-                         LogMessageDoc.CHECK_CONTROLLER )
-            void processOFPacketIn(OFPacketIn m) {
-                // we don't expect packetIn while slave, reassert we are slave
-                switchManagerCounters.packetInWhileSwitchIsSlave.increment();
-                log.warn("Received PacketIn from switch {} while" +
-                         "being slave. Reasserting slave role.", sw);
-                reassertRole(OFControllerRole.ROLE_SLAVE);
-            }
-        };
-
-
-    /**
-     * Create a new unconnected OFChannelHandler.
-     * @param controller
-     * @param broker
-     * @throws SwitchHandshakeHandlerException
-     */
-    OFSwitchHandshakeHandler(@Nonnull IOFConnectionBackend connection,
-                             @Nonnull OFFeaturesReply featuresReply,
-                             @Nonnull IOFSwitchManager switchManager,
-                             @Nonnull RoleManager roleManager,
-                             @Nonnull Timer timer) {
-        Preconditions.checkNotNull(connection, "connection");
-        Preconditions.checkNotNull(featuresReply, "featuresReply");
-        Preconditions.checkNotNull(switchManager, "switchManager");
-        Preconditions.checkNotNull(roleManager, "roleManager");
-        Preconditions.checkNotNull(timer, "timer");
-        Preconditions.checkArgument(connection.getAuxId().equals(OFAuxId.MAIN),
-                "connection must be MAIN connection but is %s", connection);
-
-        this.switchManager = switchManager;
-        this.roleManager = roleManager;
-        this.mainConnection = connection;
-        this.auxConnections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>();
-        this.featuresReply = featuresReply;
-        this.timer = timer;
-        this.switchManagerCounters = switchManager.getCounters();
-        this.factory = OFFactories.getFactory(featuresReply.getVersion());
-        this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_NS);
-        setState(new InitState());
-        this.pendingPortStatusMsg = new ArrayList<OFPortStatus>();
-
-        connection.setListener(this);
-    }
-
-    /**
-     * This begins the switch handshake. We start where the OFChannelHandler
-     * left off, right after receiving the OFFeaturesReply.
-     */
-    public void beginHandshake() {
-        Preconditions.checkState(state instanceof InitState, "must be in InitState");
-
-        if (this.featuresReply.getNTables() > 1) {
-            log.debug("Have {} table(s) for switch {}", this.featuresReply.getNTables(),
-                      getSwitchInfoString());
-            // likely supports L2 table extensions. Send set
-            //TODO @Ryan is this needed?
-            sendHandshakeL2TableSet();
-            // TODO: no L2 SET reply yet, so fire and forget the set
-        }
-
-        if (this.featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
-            setState(new WaitConfigReplyState());
-        } else {
-            // OF 1.3. Ask for Port Descriptions
-            setState(new WaitPortDescStatsReplyState());
-        }
-    }
-
-    public DatapathId getDpid(){
-        return this.featuresReply.getDatapathId();
-    }
-
-    public OFAuxId getOFAuxId(){
-        return this.featuresReply.getAuxiliaryId();
-    }
-
-    /**
-     * Is this a state in which the handshake has completed?
-     * @return true if the handshake is complete
-     */
-    public boolean isHandshakeComplete() {
-        return this.state.isHandshakeComplete();
-    }
-
-    /**
-     * Forwards to RoleChanger. See there.
-     * @param role
-     */
-    void sendRoleRequestIfNotPending(OFControllerRole role) {
-        try {
-            roleChanger.sendRoleRequestIfNotPending(role);
-        } catch (IOException e) {
-             log.error("Disconnecting switch {} due to IO Error: {}",
-                              getSwitchInfoString(), e.getMessage());
-             mainConnection.disconnect();
-        }
-    }
-
-
-    /**
-     * Forwards to RoleChanger. See there.
-     * @param role
-     */
-    void sendRoleRequest(OFControllerRole role) {
-        try {
-            roleChanger.sendRoleRequest(role);
-        } catch (IOException e) {
-             log.error("Disconnecting switch {} due to IO Error: {}",
-                              getSwitchInfoString(), e.getMessage());
-             mainConnection.disconnect();
-        }
-    }
-
-    /**
-     * Dispatches the message to the controller packet pipeline
-     */
-    private void dispatchMessage(OFMessage m) {
-        this.switchManager.handleMessage(this.sw, m, null);
-    }
-
-    /**
-     * Return a string describing this switch based on the already available
-     * information (DPID and/or remote socket)
-     * @return
-     */
-    private String getSwitchInfoString() {
-        if (sw != null)
-            return sw.toString();
-        String channelString;
-        if (mainConnection == null || mainConnection.getRemoteInetAddress() == null) {
-            channelString = "?";
-        } else {
-            channelString = mainConnection.getRemoteInetAddress().toString();
-        }
-        String dpidString;
-        if (featuresReply == null) {
-            dpidString = "?";
-        } else {
-            dpidString = featuresReply.getDatapathId().toString();
-        }
-        return String.format("[%s DPID[%s]]", channelString, dpidString);
-    }
-
-    /**
-     * Update the channels state. Only called from the state machine.
-     * TODO: enforce restricted state transitions
-     * @param state
-     */
-    private void setState(OFSwitchHandshakeState state) {
-        this.state = state;
-        state.logState();
-        state.enterState();
-    }
-
-    private void sendOFAuxSetCxnsRequest(int numAux) {
-        OFBsnSetAuxCxnsRequest request = factory.buildBsnSetAuxCxnsRequest()
-                .setNumAux(numAux)
-                .build();
-        mainConnection.write(request);
-    }
-
-    public void processOFMessage(OFMessage m) {
-        state.processOFMessage(m);
-    }
-
-    /**
-     * Send the configuration requests to tell the switch we want full
-     * packets
-     * @throws IOException
-     */
-    private void sendHandshakeSetConfig() {
-        // Ensure we receive the full packet via PacketIn
-        // FIXME: We don't set the reassembly flags.
-        OFSetConfig configSet = factory.buildSetConfig()
-                .setXid(handshakeTransactionIds--)
-                .setMissSendLen(0xffff)
-                .build();
-
-        // Barrier
-        OFBarrierRequest barrier = factory.buildBarrierRequest()
-                .setXid(handshakeTransactionIds--)
-                .build();
-
-        // Verify (need barrier?)
-        OFGetConfigRequest configReq = factory.buildGetConfigRequest()
-                .setXid(handshakeTransactionIds--)
-                .build();
-        List<OFMessage> msgList = ImmutableList.<OFMessage>of(configSet, barrier, configReq);
-        mainConnection.write(msgList);
-    }
-
-    protected void sendPortDescRequest() {
-        mainConnection.write(factory.portDescStatsRequest(ImmutableSet.<OFStatsRequestFlags>of()));
-    }
-
-    /**
-     * send a description state request
-     */
-    private void sendHandshakeDescriptionStatsRequest() {
-        // Send description stats request to set switch-specific flags
-        OFDescStatsRequest descStatsRequest = factory.buildDescStatsRequest()
-                .setXid(handshakeTransactionIds--)
-                .build();
-        mainConnection.write(descStatsRequest);
-    }
-
-    //TODO @Ryan can we nuke this as well?
-    /** send a BSN GenTable DescStats Request, querying for the tables
-     *  available at the switch.
-     * @return
-     */
-    private long sendHandshakeGenTableDescStatsRequest() {
-        long xid = handshakeTransactionIds--;
-        OFBsnGentableDescStatsRequest descStatsRequest = factory.buildBsnGentableDescStatsRequest()
-                .setXid(xid)
-                .build();
-
-        mainConnection.write(descStatsRequest);
-        return xid;
-    }
-
-    //TODO: Can we nuke this? - jason
-    /**
-     * Send an setL2TableSet message to the switch.
-     */
-    private void sendHandshakeL2TableSet() {
-        // The BsnSetL2Table message is only supported in OF 1.0, so skip if
-        // we're using a later version
-        if (factory.getVersion() != OFVersion.OF_10)
-            return;
-
-        OFBsnSetL2TableRequest m = factory.buildBsnSetL2TableRequest()
-                .setXid(handshakeTransactionIds--)
-                .setL2TableEnable(true)
-                .setL2TablePriority(1000)
-                .build();
-        mainConnection.write(m);
-    }
-
-    OFSwitchHandshakeState getStateForTesting() {
-        return state;
-    }
-
-    void reassertRole(OFControllerRole role){
-        this.roleManager.reassertRole(this, HARole.ofOFRole(role));
-    }
-
-    void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) {
-        roleChanger = new RoleChanger(TimeUnit.MILLISECONDS.toNanos(roleTimeoutMs));
-    }
-
-    /**
-     * Called by the switch manager when new aux connections have connected.
-     * This alerts the state machine of an aux connection.
-     *
-     * @param connection
-     *            the aux connection
-     */
-    public synchronized void auxConnectionOpened(IOFConnectionBackend connection) {
-        if(log.isDebugEnabled())
-            log.debug("[{}] - Switch Handshake - new aux connection {}",
-                    this.getDpid(), connection.getAuxId());
-        this.state.auxConnectionOpened(connection);
-    }
-
-    /**
-     * Gets the main connection
-     *
-     * @return the main connection
-     */
-    public IOFConnectionBackend getMainConnection() {
-        return this.mainConnection;
-    }
-
-    /**
-     * Determines if this handshake handler is responsible for the supplied
-     * connection.
-     *
-     * @param connection
-     *            an OF connection
-     * @return true if the handler has the connection
-     */
-    public boolean hasConnection(IOFConnectionBackend connection) {
-        if (this.mainConnection.equals(connection)
-            || this.auxConnections.get(connection.getAuxId()) == connection) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    void cleanup() {
-        for (IOFConnectionBackend conn : this.auxConnections.values()) {
-            conn.disconnect();
-        }
-
-        this.mainConnection.disconnect();
-    }
-
-    public String getState() {
-        return this.state.getClass().getSimpleName();
-    }
-
-    public String getQuarantineReason() {
-        if(this.state instanceof QuarantineState) {
-            QuarantineState qs = (QuarantineState) this.state;
-            return qs.getQuarantineReason();
-        }
-        return null;
-    }
-
-    /**
-     * Gets the current connections that this switch handshake handler is
-     * responsible for. Used primarily by the REST API.
-     * @return an immutable list of IOFConnections
-     */
-    public ImmutableList<IOFConnection> getConnections() {
-        ImmutableList.Builder<IOFConnection> builder = ImmutableList.builder();
-
-        builder.add(mainConnection);
-        builder.addAll(auxConnections.values());
-
-        return builder.build();
-    }
-
-
-    /** IOFConnectionListener */
-    @Override
-    public void connectionClosed(IOFConnectionBackend connection) {
-        // Disconnect handler's remaining connections
-        cleanup();
-
-        // Only remove the switch handler when the main connection is
-        // closed
-        if (connection == this.mainConnection) {
-            switchManager.handshakeDisconnected(connection.getDatapathId());
-            if(sw != null) {
-                log.debug("[{}] - main connection {} closed - disconnecting switch",
-                          connection);
-
-                setSwitchStatus(SwitchStatus.DISCONNECTED);
-                switchManager.switchDisconnected(sw);
-            }
-        }
-    }
-
-    @Override
-    public void messageReceived(IOFConnectionBackend connection, OFMessage m) {
-        processOFMessage(m);
-    }
-
-    @Override
-    public boolean isSwitchHandshakeComplete(IOFConnectionBackend connection) {
-        return state.isHandshakeComplete();
-    }
-
-    public void setSwitchStatus(SwitchStatus status) {
-        if(sw != null) {
-            SwitchStatus oldStatus = sw.getStatus();
-            if(oldStatus != status) {
-            	log.debug("[{}] SwitchStatus change to {} requested, switch is in status " + oldStatus,
-                        mainConnection.getDatapathId(), status);
-                sw.setStatus(status);
-                switchManager.switchStatusChanged(sw, oldStatus, status);
-            } else {
-                log.warn("[{}] SwitchStatus change to {} requested, switch is already in status",
-                        mainConnection.getDatapathId(), status);
-            }
-        } else {
-            log.warn("[{}] SwitchStatus change to {} requested, but switch is not allocated yet",
-                    mainConnection.getDatapathId(), status);
-        }
-    }
+	private static final Logger log = LoggerFactory.getLogger(OFSwitchHandshakeHandler.class);
+
+	private final IOFSwitchManager switchManager;
+	private final RoleManager roleManager;
+	private final IOFConnectionBackend mainConnection;
+	private final SwitchManagerCounters switchManagerCounters;
+	private IOFSwitchBackend sw;
+	private final Map<OFAuxId, IOFConnectionBackend> auxConnections;
+	private volatile OFSwitchHandshakeState state;
+	private RoleChanger roleChanger;
+	// Default to 1.3 - This is overwritten by the features reply
+	private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
+	private final OFFeaturesReply featuresReply;
+	private final Timer timer;
+
+	private final ArrayList<OFPortStatus> pendingPortStatusMsg;
+
+	/** transaction Ids to use during handshake. Since only one thread
+	 * calls into the OFChannelHandler we don't need atomic.
+	 * We will count down
+	 */
+	private long handshakeTransactionIds = 0x00FFFFFFFFL;
+
+	/* Exponential backoff of master role assertion */
+	private final long MAX_ASSERT_TIME_INTERVAL_NS = TimeUnit.SECONDS.toNanos(120);
+	private final long DEFAULT_ROLE_TIMEOUT_NS = TimeUnit.SECONDS.toNanos(10);
+
+	protected OFPortDescStatsReply portDescStats;
+
+	/**
+	 * When we remove a pending role request and set the role on the switch
+	 * we use this enum to indicate how we arrived at the decision.
+	 * @author gregor
+	 */
+	private enum RoleRecvStatus {
+		/** We received a role reply message from the switch */
+		RECEIVED_REPLY,
+		/** The switch returned an error indicated that roles are not
+		 * supported*/
+		UNSUPPORTED,
+		/** The request timed out */
+		NO_REPLY;
+	}
+	/**
+	 * A utility class to handle role requests and replies for this channel.
+	 * After a role request is submitted the role changer keeps track of the
+	 * pending request, collects the reply (if any) and times out the request
+	 * if necessary.
+	 *
+	 * To simplify role handling we only keep track of the /last/ pending
+	 * role reply send to the switch. If multiple requests are pending and
+	 * we receive replies for earlier requests we ignore them. However, this
+	 * way of handling pending requests implies that we could wait forever if
+	 * a new request is submitted before the timeout triggers. If necessary
+	 * we could work around that though.
+	 * @author gregor
+	 */
+	private class RoleChanger {
+		// indicates that a request is currently pending
+		// needs to be volatile to allow correct double-check idiom
+		private volatile boolean requestPending;
+		// the transaction Id of the pending request
+		private long pendingXid;
+		// the role that's pending
+		private OFControllerRole pendingRole;
+		// system time in NS when we send the request
+		private long roleSubmitTimeNs;
+		// the timeout to use
+		private final long roleTimeoutNs;
+		private long lastAssertTimeNs;
+		private long assertTimeIntervalNs = TimeUnit.SECONDS.toNanos(1);
+
+		public RoleChanger(long roleTimeoutNs) {
+			this.roleTimeoutNs = roleTimeoutNs;
+			// System.nanoTime() may be negative -- prime the roleSubmitTime as
+			// "long ago in the past" to be robust against it.
+			this.roleSubmitTimeNs = System.nanoTime() - (2 * roleTimeoutNs);
+			this.lastAssertTimeNs = System.nanoTime() - (2 * assertTimeIntervalNs);
+			this.requestPending = false;
+			this.pendingXid = -1;
+			this.pendingRole = null;
+		}
+
+		/**
+		 * Send Nicira role request message to the switch requesting the
+		 * specified role.
+		 *
+		 * @param role role to request
+		 */
+		private long sendNiciraRoleRequest(OFControllerRole role){
+
+			long xid;
+			// Construct the role request message
+			if(factory.getVersion().compareTo(OFVersion.OF_12) < 0) {
+				OFNiciraControllerRoleRequest.Builder builder =
+						factory.buildNiciraControllerRoleRequest();
+				xid = factory.nextXid();
+				builder.setXid(xid);
+
+				OFNiciraControllerRole niciraRole = NiciraRoleUtils.ofRoleToNiciraRole(role);
+				builder.setRole(niciraRole);
+				OFNiciraControllerRoleRequest roleRequest = builder.build();
+				// Send it to the switch
+				mainConnection.write(roleRequest);
+			} else {
+				// send an OF 1.2+ role request
+				OFRoleRequest roleRequest = factory.buildRoleRequest()
+						// we don't use the generation id scheme for now,
+						// switch initializes to 0, we keep it at 0
+						.setGenerationId(U64.of(0))
+						.setRole(role)
+						.build();
+				xid = roleRequest.getXid();
+				mainConnection.write(roleRequest);
+			}
+			return xid;
+		}
+
+		/**
+		 * Send a role request for the given role only if no other role
+		 * request is currently pending.
+		 * @param role The role to send to the switch.
+		 * @throws IOException
+		 */
+		@LogMessageDoc(level="WARN",
+				message="Reasserting master role on switch {SWITCH}, " +
+						"likely a configruation error with multiple masters",
+						explanation="The controller keeps getting permission error " +
+								"from switch, likely due to switch connected to another " +
+								"controller also in master mode",
+								recommendation=LogMessageDoc.CHECK_SWITCH)
+		synchronized void sendRoleRequestIfNotPending(OFControllerRole role)
+				throws IOException {
+			long now = System.nanoTime();
+			if (now - lastAssertTimeNs < assertTimeIntervalNs) {
+				return;
+			}
+
+			lastAssertTimeNs = now;
+			if (assertTimeIntervalNs < MAX_ASSERT_TIME_INTERVAL_NS) { // 2 minutes max
+				assertTimeIntervalNs <<= 1;
+			} else if (role == OFControllerRole.ROLE_MASTER){
+				log.warn("Reasserting master role on switch {}, " +
+						"likely a switch config error with multiple masters",
+						role, sw);
+			}
+			if (!requestPending)
+				sendRoleRequest(role);
+			else
+				switchManagerCounters.roleNotResentBecauseRolePending.increment();
+		}
+
+		/**
+		 * Send a role request with the given role to the switch.
+		 *
+		 * Send a role request with the given role to the switch and update
+		 * the pending request and timestamp.
+		 *
+		 * @param role
+		 * @throws IOException
+		 */
+		synchronized void sendRoleRequest(OFControllerRole role) throws IOException {
+			/*
+			 * There are three cases to consider for SUPPORTS_NX_ROLE:
+			 *
+			 * 1) unset. We have neither received a role reply from the
+			 *    switch nor has a request timed out. Send a request.
+			 * 2) TRUE: We've already send a request earlier and received
+			 *    a reply. The switch supports role and we should send one.
+			 * 3) FALSE: We have already send a role and received an error.
+			 *    The switch does not support roles. Don't send a role request,
+			 *    set the switch's role directly.
+			 */
+			Boolean supportsNxRole = (Boolean)
+					sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE);
+			if ((supportsNxRole != null) && !supportsNxRole) {
+				setSwitchRole(role, RoleRecvStatus.UNSUPPORTED);
+			} else {
+				pendingXid = sendNiciraRoleRequest(role);
+				pendingRole = role;
+				this.roleSubmitTimeNs = System.nanoTime();
+				requestPending = true;
+			}
+		}
+
+		/**
+		 * Deliver a received role reply and set SWITCH_SUPPORTS_NX_ROLE.
+		 *
+		 * Check if a request is pending and if the received reply matches the
+		 * the expected pending reply (we check both role and xid) we set
+		 * the role for the switch/channel.
+		 *
+		 * If a request is pending but doesn't match the reply we ignore it.
+		 *
+		 * If no request is pending we disconnect.
+		 *
+		 * @param xid
+		 * @param role
+		 * @throws SwitchStateException if no request is pending
+		 */
+		synchronized void deliverRoleReply(long xid, OFControllerRole role) {
+			if (!requestPending) {
+				// Maybe don't disconnect if the role reply we received is
+				// for the same role we are already in.
+				String msg = String.format("Switch: [%s], State: [%s], "
+						+ "received unexpected RoleReply[%s]. "
+						+ "No roles are pending",
+						OFSwitchHandshakeHandler.this.getSwitchInfoString(),
+						OFSwitchHandshakeHandler.this.state.toString(),
+						role);
+				throw new SwitchStateException(msg);
+			}
+
+			if (pendingXid == xid && pendingRole == role) {
+				log.debug("[{}] Received role reply message setting role to {}",
+						getDpid(), role);
+				switchManagerCounters.roleReplyReceived.increment();
+				setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY);
+			} else {
+				log.debug("[{}] Received stale or unexpected role reply " +
+						"{}, xid={}. Ignoring. " +
+						"Waiting for {}, xid={}",
+						new Object[] { getDpid(), role, xid,
+						pendingRole, pendingXid });
+			}
+		}
+
+		/**
+		 * Called if we receive an  error message. If the xid matches the
+		 * pending request we handle it otherwise we ignore it. We also
+		 * set SWITCH_SUPPORTS_NX_ROLE to false.
+		 *
+		 * Note: since we only keep the last pending request we might get
+		 * error messages for earlier role requests that we won't be able
+		 * to handle
+		 * @param xid
+		 * @return true if the error was handled by us, false otherwise
+		 * @throws SwitchStateException if the error was for the pending
+		 * role request but was unexpected
+		 */
+		synchronized boolean deliverError(OFErrorMsg error) {
+			if (!requestPending)
+				return false;
+
+			if (pendingXid == error.getXid()) {
+				if (error.getErrType() == OFErrorType.BAD_REQUEST) {
+					switchManagerCounters.roleReplyErrorUnsupported.increment();
+					setSwitchRole(pendingRole, RoleRecvStatus.UNSUPPORTED);
+				} else {
+					// TODO: Is this the right thing to do if we receive
+					// some other error besides a bad request error?
+					// Presumably that means the switch did actually
+					// understand the role request message, but there
+					// was some other error from processing the message.
+					// OF 1.2 specifies a ROLE_REQUEST_FAILED
+					// error code, but it doesn't look like the Nicira
+					// role request has that. Should check OVS source
+					// code to see if it's possible for any other errors
+					// to be returned.
+					// If we received an error the switch is not
+					// in the correct role, so we need to disconnect it.
+					// We could also resend the request but then we need to
+					// check if there are other pending request in which
+					// case we shouldn't resend. If we do resend we need
+					// to make sure that the switch eventually accepts one
+					// of our requests or disconnect the switch. This feels
+					// cumbersome.
+					String msg = String.format("Switch: [%s], State: [%s], "
+							+ "Unexpected error %s in respone to our "
+							+ "role request for %s.",
+							OFSwitchHandshakeHandler.this.getSwitchInfoString(),
+							OFSwitchHandshakeHandler.this.state.toString(),
+							error.toString(),
+							pendingRole);
+					throw new SwitchStateException(msg);
+				}
+				return true;
+			}
+			return false;
+		}
+
+		/**
+		 * Check if a pending role request has timed out.
+		 */
+		void checkTimeout() {
+			if (!requestPending)
+				return;
+			synchronized(this) {
+				if (!requestPending)
+					return;
+				long now = System.nanoTime();
+				if (now - this.roleSubmitTimeNs > roleTimeoutNs) {
+					// timeout triggered.
+					switchManagerCounters.roleReplyTimeout.increment();
+					setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY);
+				}
+			}
+		}
+
+		/**
+		 * Set the role for this switch / channel.
+		 *
+		 * If the status indicates that we received a reply we set the role.
+		 * If the status indicates otherwise we disconnect the switch if
+		 * the role is SLAVE.
+		 *
+		 * "Setting a role" means setting the appropriate ChannelState,
+		 * setting the flags on the switch and
+		 * notifying Controller.java about new role of the switch
+		 *
+		 * @param role The role to set.
+		 * @param status How we derived at the decision to set this status.
+		 */
+		synchronized private void setSwitchRole(OFControllerRole role, RoleRecvStatus status) {
+			requestPending = false;
+			if (status == RoleRecvStatus.RECEIVED_REPLY)
+				sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
+			else
+				sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+			sw.setControllerRole(role);
+
+			if (role != OFControllerRole.ROLE_SLAVE) {
+				OFSwitchHandshakeHandler.this.setState(new MasterState());
+			} else {
+				if (status != RoleRecvStatus.RECEIVED_REPLY) {
+					if (log.isDebugEnabled()) {
+						log.debug("Disconnecting switch {}. Doesn't support role"
+								+ "({}) request and controller is now SLAVE",
+								getSwitchInfoString(), status);
+					}
+					// the disconnect will trigger a switch removed to
+					// controller so no need to signal anything else
+					sw.disconnect();
+				} else {
+					OFSwitchHandshakeHandler.this.setState(new SlaveState());
+				}
+			}
+		}
+	}
+
+	/**
+	 * Default implementation for message handlers in any state.
+	 *
+	 * Individual states must override these if they want a behavior
+	 * that differs from the default.
+	 *
+	 * In general, these handlers simply ignore the message and do
+	 * nothing.
+	 *
+	 * There are some exceptions though, since some messages really
+	 * are handled the same way in every state (e.g., ECHO_REQUST) or
+	 * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY
+	 */
+	public abstract class OFSwitchHandshakeState {
+
+		void processOFBarrierReply(OFBarrierReply m) {
+			// do nothing
+		}
+
+		void processOFError(OFErrorMsg m) {
+			logErrorDisconnect(m);
+		}
+
+		void processOFFlowRemoved(OFFlowRemoved m) {
+			unhandledMessageReceived(m);
+		}
+
+		void processOFGetConfigReply(OFGetConfigReply m) {
+			// we only expect config replies in the WAIT_CONFIG_REPLY state
+			// TODO: might use two different strategies depending on whether
+			// we got a miss length of 64k or not.
+			illegalMessageReceived(m);
+		}
+
+		void processOFPacketIn(OFPacketIn m) {
+			unhandledMessageReceived(m);
+		}
+
+		// By default add port status messages to a pending list
+		void processOFPortStatus(OFPortStatus m) {
+			pendingPortStatusMsg.add(m);
+		}
+
+		void processOFQueueGetConfigReply(OFQueueGetConfigReply m) {
+			unhandledMessageReceived(m);
+		}
+
+		void processOFStatsReply(OFStatsReply m) {
+			switch(m.getStatsType()) {
+			case PORT_DESC:
+				processPortDescStatsReply((OFPortDescStatsReply) m);
+				break;
+			default:
+				unhandledMessageReceived(m);
+			}
+		}
+
+		void processOFExperimenter(OFExperimenter m) {
+			unhandledMessageReceived(m);
+		}
+
+		void processPortDescStatsReply(OFPortDescStatsReply m) {
+			unhandledMessageReceived(m);
+		}
+
+		void processOFRoleReply(OFRoleReply m) {
+			unhandledMessageReceived(m);
+		}
+
+		private final boolean handshakeComplete;
+		OFSwitchHandshakeState(boolean handshakeComplete) {
+			this.handshakeComplete = handshakeComplete;
+		}
+
+		void logState() {
+			if(log.isDebugEnabled())
+				log.debug("[{}] - Switch Handshake - enter state {}", mainConnection.getDatapathId(), this.getClass().getSimpleName());
+		}
+
+		/** enter this state. Can initialize the handler, send
+		 *  the necessary messages, etc.
+		 */
+		void enterState(){
+		}
+
+		/**
+		 * Is this a state in which the handshake has completed?
+		 * @return true if the handshake is complete
+		 */
+		public boolean isHandshakeComplete() {
+			return handshakeComplete;
+		}
+
+		/**
+		 * Used to notify the WAIT OF AUX state that
+		 * a new connection has been added
+		 * @param connection
+		 */
+		public void auxConnectionOpened(IOFConnectionBackend connection) {
+			// Should only be handled in wait of aux
+			log.debug("[{}] - Switch Handshake - unhandled aux connection event",
+					getDpid());
+		}
+		/**
+		 * Get a string specifying the switch connection, state, and
+		 * message received. To be used as message for SwitchStateException
+		 * or log messages
+		 * @param h The channel handler (to get switch information_
+		 * @param m The OFMessage that has just been received
+		 * @param details A string giving more details about the exact nature
+		 * of the problem.
+		 * @return
+		 */
+		// needs to be protected because enum members are acutally subclasses
+		protected String getSwitchStateMessage(OFMessage m,
+				String details) {
+			return String.format("Switch: [%s], State: [%s], received: [%s]"
+					+ ", details: %s",
+					getSwitchInfoString(),
+					this.toString(),
+					m.getType().toString(),
+					details);
+		}
+
+		/**
+		 * We have an OFMessage we didn't expect given the current state and
+		 * we want to treat this as an error.
+		 * We currently throw an exception that will terminate the connection
+		 * However, we could be more forgiving
+		 * @param h the channel handler that received the message
+		 * @param m the message
+		 * @throws SwitchStateExeption we always through the execption
+		 */
+		// needs to be protected because enum members are acutally subclasses
+		protected void illegalMessageReceived(OFMessage m) {
+			String msg = getSwitchStateMessage(m,
+					"Switch should never send this message in the current state");
+			throw new SwitchStateException(msg);
+
+		}
+
+		/**
+		 * We have an OFMessage we didn't expect given the current state and
+		 * we want to ignore the message
+		 * @param h the channel handler the received the message
+		 * @param m the message
+		 */
+		protected void unhandledMessageReceived(OFMessage m) {
+			switchManagerCounters.unhandledMessage.increment();
+			if (log.isDebugEnabled()) {
+				String msg = getSwitchStateMessage(m,
+						"Ignoring unexpected message");
+				log.debug(msg);
+			}
+		}
+
+		/**
+		 * Log an OpenFlow error message from a switch
+		 * @param error The error message
+		 */
+		@LogMessageDoc(level="ERROR",
+				message="Error {error type} {error code} from {switch} " +
+						"in state {state}",
+						explanation="The switch responded with an unexpected error" +
+								"to an OpenFlow message from the controller",
+								recommendation="This could indicate improper network operation. " +
+										"If the problem persists restarting the switch and " +
+										"controller may help."
+				)
+		protected void logError(OFErrorMsg error) {
+			log.error("{} from switch {} in state {}",
+					new Object[] {
+					error.toString(),
+					getSwitchInfoString(),
+					this.toString()});
+		}
+
+		/**
+		 * Log an OpenFlow error message from a switch and disconnect the
+		 * channel
+		 * @param error The error message
+		 */
+		protected void logErrorDisconnect(OFErrorMsg error) {
+			logError(error);
+			mainConnection.disconnect();
+		}
+
+		/**
+		 * Extract the role from an OFVendor message.
+		 *
+		 * Extract the role from an OFVendor message if the message is a
+		 * Nicira role reply. Otherwise return null.
+		 *
+		 * @param h The channel handler receiving the message
+		 * @param vendorMessage The vendor message to parse.
+		 * @return The role in the message if the message is a Nicira role
+		 * reply, null otherwise.
+		 */
+		protected OFControllerRole extractNiciraRoleReply(OFMessage vendorMessage) {
+			if (!(vendorMessage instanceof OFNiciraControllerRoleReply))
+				return null;
+			OFNiciraControllerRoleReply roleReply =
+					(OFNiciraControllerRoleReply) vendorMessage;
+			return NiciraRoleUtils.niciraToOFRole(roleReply);
+		}
+
+		/**
+		 * Handle a port status message.
+		 *
+		 * Handle a port status message by updating the port maps in the
+		 * IOFSwitch instance and notifying Controller about the change so
+		 * it can dispatch a switch update.
+		 *
+		 * @param h The OFChannelHhandler that received the message
+		 * @param m The PortStatus message we received
+		 * @param doNotify if true switch port changed events will be
+		 * dispatched
+		 */
+		protected void handlePortStatusMessage(OFPortStatus m, boolean doNotify) {
+			if (sw == null) {
+				String msg = getSwitchStateMessage(m, "State machine error: switch is null. Should never happen");
+				throw new SwitchStateException(msg);
+			}
+			Collection<PortChangeEvent> changes = sw.processOFPortStatus(m);
+			if (doNotify) {
+				for (PortChangeEvent ev: changes)
+					switchManager.notifyPortChanged(sw, ev.port, ev.type);
+			}
+		}
+
+		/**
+		 * Process an OF message received on the channel and
+		 * update state accordingly.
+		 *
+		 * The main "event" of the state machine. Process the received message,
+		 * send follow up message if required and update state if required.
+		 *
+		 * Switches on the message type and calls more specific event handlers
+		 * for each individual OF message type. If we receive a message that
+		 * is supposed to be sent from a controller to a switch we throw
+		 * a SwitchStateExeption.
+		 *
+		 * The more specific handlers can also throw SwitchStateExceptions
+		 *
+		 * @param h The OFChannelHandler that received the message
+		 * @param m The message we received.
+		 * @throws SwitchStateException
+		 * @throws IOException
+		 */
+		void processOFMessage(OFMessage m) {
+			roleChanger.checkTimeout();
+			switch(m.getType()) {
+			case BARRIER_REPLY:
+				processOFBarrierReply((OFBarrierReply) m);
+				break;
+			case ERROR:
+				processOFError((OFErrorMsg) m);
+				break;
+			case FLOW_REMOVED:
+				processOFFlowRemoved((OFFlowRemoved) m);
+				break;
+			case GET_CONFIG_REPLY:
+				processOFGetConfigReply((OFGetConfigReply) m);
+				break;
+			case PACKET_IN:
+				processOFPacketIn((OFPacketIn) m);
+				break;
+			case PORT_STATUS:
+				processOFPortStatus((OFPortStatus) m);
+				break;
+			case QUEUE_GET_CONFIG_REPLY:
+				processOFQueueGetConfigReply((OFQueueGetConfigReply) m);
+				break;
+			case STATS_REPLY:
+				processOFStatsReply((OFStatsReply) m);
+				break;
+			case ROLE_REPLY:
+				processOFRoleReply((OFRoleReply) m);
+				break;
+			case EXPERIMENTER:
+				processOFExperimenter((OFExperimenter) m);
+				break;
+			default:
+				illegalMessageReceived(m);
+				break;
+			}
+		}
+	}
+
+	/**
+	 * Initial state before channel is connected. Should not handle any messages.
+	 */
+	public class InitState extends OFSwitchHandshakeState {
+
+		InitState() {
+			super(false);
+		}
+
+		@Override
+		public void logState() {
+			log.debug("[{}] - Switch Handshake - Initiating from {}",
+					getDpid(), mainConnection.getRemoteInetAddress());
+		}
+	}
+
+	/**
+	 * We are waiting for a features reply message. Once we receive it
+	 * we send a SetConfig request, barrier, and GetConfig request.
+	 * Next stats is WAIT_CONFIG_REPLY or WAIT_SET_L2_TABLE_REPLY
+	 */
+	public class WaitPortDescStatsReplyState extends OFSwitchHandshakeState {
+		WaitPortDescStatsReplyState() {
+			super(false);
+		}
+
+		@Override
+		void enterState(){
+			sendPortDescRequest();
+		}
+
+		@Override
+		void processPortDescStatsReply(OFPortDescStatsReply  m) {
+			portDescStats = m;
+			setState(new WaitConfigReplyState());
+		}
+
+		@Override
+		void processOFExperimenter(OFExperimenter m) {
+			unhandledMessageReceived(m);
+		}
+	}
+
+	/**
+	 * We are waiting for a config reply message. Once we receive it
+	 * we send a DescriptionStatsRequest to the switch.
+	 * Next state: WAIT_DESCRIPTION_STAT_REPLY
+	 */
+	public class WaitConfigReplyState extends OFSwitchHandshakeState {
+
+		WaitConfigReplyState() {
+			super(false);
+		}
+
+		@Override
+		@LogMessageDocs({
+			@LogMessageDoc(level="WARN",
+					message="Config Reply from {switch} has " +
+							"miss length set to {length}",
+							explanation="The controller requires that the switch " +
+									"use a miss length of 0xffff for correct " +
+									"function",
+									recommendation="Use a different switch to ensure " +
+					"correct function")
+		})
+		void processOFGetConfigReply(OFGetConfigReply m) {
+			if (m.getMissSendLen() == 0xffff) {
+				log.trace("Config Reply from switch {} confirms "
+						+ "miss length set to 0xffff",
+						getSwitchInfoString());
+			} else {
+				// FIXME: we can't really deal with switches that don't send
+				// full packets. Shouldn't we drop the connection here?
+				// FIXME: count??
+				log.warn("Config Reply from switch {} has"
+						+ "miss length set to {}",
+						getSwitchInfoString(),
+						m.getMissSendLen());
+			}
+			setState(new WaitDescriptionStatReplyState());
+		}
+
+		@Override
+		void processOFStatsReply(OFStatsReply  m) {
+			illegalMessageReceived(m);
+		}
+
+		@Override
+		void processOFError(OFErrorMsg m) {
+			logErrorDisconnect(m);
+		}
+
+		@Override
+		void enterState() {
+			sendHandshakeSetConfig();
+		}
+	}
+
+	/**
+	 * We are waiting for a OFDescriptionStat message from the switch.
+	 * Once we receive any stat message we try to parse it. If it's not
+	 * a description stats message we disconnect. If its the expected
+	 * description stats message, we:
+	 *    - use the switch driver to bind the switch and get an IOFSwitch
+	 *      instance, setup the switch instance
+	 *    - setup the IOFSwitch instance
+	 *    - add switch to FloodlightProvider and send the intial role
+	 *      request to the switch.
+	 *
+	 * Next state: WaitOFAuxCxnsReplyState (if OF1.3), else
+	 *     WaitInitialRoleState or WaitSwitchDriverSubHandshake
+	 *
+	 * All following states will have a h.sw instance!
+	 */
+	public class WaitDescriptionStatReplyState extends OFSwitchHandshakeState{
+
+		WaitDescriptionStatReplyState() {
+			super(false);
+		}
+
+		@LogMessageDoc(message="Switch {switch info} bound to class " +
+				"{switch driver}, description {switch description}",
+				explanation="The specified switch has been bound to " +
+						"a switch driver based on the switch description" +
+				"received from the switch")
+		@Override
+		void processOFStatsReply(OFStatsReply m) {
+			// Read description, if it has been updated
+			if (m.getStatsType() != OFStatsType.DESC) {
+				illegalMessageReceived(m);
+				return;
+			}
+
+			OFDescStatsReply descStatsReply = (OFDescStatsReply) m;
+			SwitchDescription description = new SwitchDescription(descStatsReply);
+			sw = switchManager.getOFSwitchInstance(mainConnection, description, factory, featuresReply.getDatapathId());
+			switchManager.switchAdded(sw);
+			// set switch information
+			// set features reply and channel first so we a DPID and
+			// channel info.
+			sw.setFeaturesReply(featuresReply);
+			if (portDescStats != null) {
+				sw.setPortDescStats(portDescStats);
+			}
+
+			// Handle pending messages now that we have a sw object
+			handlePendingPortStatusMessages(description);
+
+			sw.startDriverHandshake();
+			if (sw.isDriverHandshakeComplete()) {
+				setState(new WaitAppHandshakeState());
+			} else {
+				setState(new WaitSwitchDriverSubHandshakeState());
+			}
+		}
+
+		void handlePendingPortStatusMessages(SwitchDescription description){
+			for (OFPortStatus ps: pendingPortStatusMsg) {
+				handlePortStatusMessage(ps, false);
+			}
+			pendingPortStatusMsg.clear();
+			log.info("Switch {} bound to class {}, description {}", new Object[] { sw, sw.getClass(), description });
+		}
+
+		@Override
+		void enterState() {
+			sendHandshakeDescriptionStatsRequest();
+		}
+	}
+
+	public class WaitSwitchDriverSubHandshakeState extends OFSwitchHandshakeState {
+
+		WaitSwitchDriverSubHandshakeState() {
+			super(false);
+		}
+
+		@Override
+		void processOFMessage(OFMessage m) {
+			// FIXME: other message to handle here?
+			sw.processDriverHandshakeMessage(m);
+			if (sw.isDriverHandshakeComplete()) {
+				setState(new WaitAppHandshakeState());
+			}
+		}
+
+		@Override
+		void processOFPortStatus(OFPortStatus m) {
+			handlePortStatusMessage(m, false);
+		}
+	}
+
+	public class WaitAppHandshakeState extends OFSwitchHandshakeState {
+
+		private final Iterator<IAppHandshakePluginFactory> pluginIterator;
+		private OFSwitchAppHandshakePlugin plugin;
+
+		WaitAppHandshakeState() {
+			super(false);
+			this.pluginIterator = switchManager.getHandshakePlugins().iterator();
+		}
+
+		@Override
+		void processOFMessage(OFMessage m) {
+			if(m.getType() == OFType.PORT_STATUS){
+				OFPortStatus status = (OFPortStatus) m;
+				handlePortStatusMessage(status, false);
+			}
+			else if(plugin != null){
+				this.plugin.processOFMessage(m);
+			}
+			else{
+				super.processOFMessage(m);
+			}
+		}
+
+		/**
+		 * Called by handshake plugins to signify that they have finished their
+		 * sub handshake.
+		 *
+		 * @param result
+		 *            the result of the sub handshake
+		 */
+		void exitPlugin(PluginResult result) {
+
+			// Proceed
+			if (result.getResultType() == PluginResultType.CONTINUE) {
+				if (log.isDebugEnabled()) {
+					log.debug("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}."
+							+ " Proceeding normally..",
+							this.plugin.getClass().getSimpleName(), result);
+				}
+
+				enterNextPlugin();
+
+				// Stop
+			} else if (result.getResultType() == PluginResultType.DISCONNECT) {
+				log.error("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. "
+						+ "Disconnecting switch.",
+						this.plugin.getClass().getSimpleName(), result);
+				mainConnection.disconnect();
+			} else if (result.getResultType() == PluginResultType.QUARANTINE) {
+				log.warn("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. "
+						+ "Putting switch into quarantine state.",
+						this.plugin.getClass().getSimpleName(),
+						result);
+				setState(new QuarantineState(result.getReason()));
+			}
+		}
+
+		@Override
+		public void enterState() {
+			enterNextPlugin();
+		}
+
+		/**
+		 * Initialize the plugin and begin.
+		 *
+		 * @param plugin the of switch app handshake plugin
+		 */
+		public void enterNextPlugin() {
+			if(this.pluginIterator.hasNext()){
+				this.plugin = pluginIterator.next().createPlugin();
+				this.plugin.init(this, sw, timer);
+				this.plugin.enterPlugin();
+			}
+			// No more plugins left...
+			else{
+				setState(new WaitInitialRoleState());
+			}
+		}
+
+		@Override
+		void processOFPortStatus(OFPortStatus m) {
+			handlePortStatusMessage(m, false);
+		}
+
+		OFSwitchAppHandshakePlugin getCurrentPlugin() {
+			return plugin;
+		}
+
+	}
+
+	/**
+	 * Switch is in a quarantine state. Essentially the handshake is complete.
+	 */
+	public class QuarantineState extends OFSwitchHandshakeState {
+
+		private final String quarantineReason;
+
+		QuarantineState(String reason) {
+			super(true);
+			this.quarantineReason = reason;
+		}
+
+		@Override
+		public void enterState() {
+			setSwitchStatus(SwitchStatus.QUARANTINED);
+		}
+
+		@Override
+		void processOFPortStatus(OFPortStatus m) {
+			handlePortStatusMessage(m, false);
+		}
+
+		public String getQuarantineReason() {
+			return this.quarantineReason;
+		}
+	}
+
+	/**
+	 * We are waiting for the initial role reply message (or error indication)
+	 * from the switch. Next State: MASTER or SLAVE
+	 */
+	public class WaitInitialRoleState extends OFSwitchHandshakeState {
+
+		WaitInitialRoleState() {
+			super(false);
+		}
+
+		@Override
+		void processOFError(OFErrorMsg m) {
+			// role changer will ignore the error if it isn't for it
+			boolean didHandle = roleChanger.deliverError(m);
+			if (!didHandle) {
+				logError(m);
+			}
+		}
+
+		@Override
+		void processOFExperimenter(OFExperimenter m) {
+			OFControllerRole role = extractNiciraRoleReply(m);
+			// If role == null it measn the message wasn't really a
+			// Nicira role reply. We ignore this case.
+			if (role != null) {
+				roleChanger.deliverRoleReply(m.getXid(), role);
+			} else {
+				unhandledMessageReceived(m);
+			}
+		}
+
+		@Override
+		void processOFRoleReply(OFRoleReply m) {
+			roleChanger.deliverRoleReply(m.getXid(), m.getRole());
+		}
+
+		@Override
+		void processOFStatsReply(OFStatsReply m) {
+			illegalMessageReceived(m);
+		}
+
+		@Override
+		void processOFPortStatus(OFPortStatus m) {
+			handlePortStatusMessage(m, false);
+		}
+
+		@Override
+		void enterState(){
+			sendRoleRequest(roleManager.getOFControllerRole());
+		}
+	}
+
+	/**
+	 * The switch is in MASTER role. We enter this state after a role
+	 * reply from the switch is received (or the controller is MASTER
+	 * and the switch doesn't support roles). The handshake is complete at
+	 * this point. We only leave this state if the switch disconnects or
+	 * if we send a role request for SLAVE /and/ receive the role reply for
+	 * SLAVE.
+	 */
+	public class MasterState extends OFSwitchHandshakeState {
+
+		MasterState() {
+			super(true);
+		}
+
+		@Override
+		void enterState() {
+			setSwitchStatus(SwitchStatus.MASTER);
+		}
+
+		@LogMessageDoc(level="WARN",
+				message="Received permission error from switch {} while" +
+						"being master. Reasserting master role.",
+						explanation="The switch has denied an operation likely " +
+								"indicating inconsistent controller roles",
+								recommendation="This situation can occurs transiently during role" +
+										" changes. If, however, the condition persists or happens" +
+										" frequently this indicates a role inconsistency. " +
+										LogMessageDoc.CHECK_CONTROLLER )
+		@Override
+		void processOFError(OFErrorMsg m) {
+			// role changer will ignore the error if it isn't for it
+			boolean didHandle = roleChanger.deliverError(m);
+			if (didHandle)
+				return;
+			if ((m.getErrType() == OFErrorType.BAD_REQUEST) &&
+					(((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.EPERM)) {
+				// We are the master controller and the switch returned
+				// a permission error. This is a likely indicator that
+				// the switch thinks we are slave. Reassert our
+				// role
+				// FIXME: this could be really bad during role transitions
+				// if two controllers are master (even if its only for
+				// a brief period). We might need to see if these errors
+				// persist before we reassert
+				switchManagerCounters.epermErrorWhileSwitchIsMaster.increment();
+				log.warn("Received permission error from switch {} while" +
+						"being master. Reasserting master role.",
+						getSwitchInfoString());
+				reassertRole(OFControllerRole.ROLE_MASTER);
+			}
+			else if ((m.getErrType() == OFErrorType.FLOW_MOD_FAILED) &&
+					(((OFFlowModFailedErrorMsg)m).getCode() == OFFlowModFailedCode.ALL_TABLES_FULL)) {
+				sw.setTableFull(true);
+			}
+			else {
+				logError(m);
+			}
+			dispatchMessage(m);
+		}
+
+		@Override
+		void processOFExperimenter(OFExperimenter m) {
+			OFControllerRole role = extractNiciraRoleReply(m);
+			// If role == null it means the message wasn't really a
+			// Nicira role reply. We ignore just dispatch it to the
+			// OFMessage listenersa in this case.
+			if (role != null) {
+				roleChanger.deliverRoleReply(m.getXid(), role);
+			} else {
+				dispatchMessage(m);
+			}
+		}
+
+
+		@Override
+		void processOFRoleReply(OFRoleReply m) {
+			roleChanger.deliverRoleReply(m.getXid(), m.getRole());
+		}
+
+		@Override
+		void processOFPortStatus(OFPortStatus m) {
+			handlePortStatusMessage(m, true);
+		}
+
+		@Override
+		void processOFPacketIn(OFPacketIn m) {
+			dispatchMessage(m);
+		}
+
+		@Override
+		void processOFFlowRemoved(OFFlowRemoved m) {
+			dispatchMessage(m);
+		}
+	}
+
+	/**
+	 * The switch is in SLAVE role. We enter this state after a role
+	 * reply from the switch is received. The handshake is complete at
+	 * this point. We only leave this state if the switch disconnects or
+	 * if we send a role request for MASTER /and/ receive the role reply for
+	 * MASTER.
+	 * TODO: CURRENTLY, WE DO NOT DISPATCH ANY MESSAGE IN SLAVE.
+	 */
+	public class SlaveState extends OFSwitchHandshakeState {
+
+		SlaveState() {
+			super(true);
+		}
+
+		@Override
+		void enterState() {
+			setSwitchStatus(SwitchStatus.SLAVE);
+		}
+
+		@Override
+		void processOFError(OFErrorMsg m) {
+			// role changer will ignore the error if it isn't for it
+			boolean didHandle = roleChanger.deliverError(m);
+			if (!didHandle) {
+				logError(m);
+			}
+		}
+
+		@Override
+		void processOFStatsReply(OFStatsReply m) {
+		}
+
+		@Override
+		void processOFPortStatus(OFPortStatus m) {
+			handlePortStatusMessage(m, true);
+		}
+
+		@Override
+		void processOFExperimenter(OFExperimenter m) {
+			OFControllerRole role = extractNiciraRoleReply(m);
+			// If role == null it means the message wasn't really a
+			// Nicira role reply. We ignore it.
+			if (role != null) {
+				roleChanger.deliverRoleReply(m.getXid(), role);
+			} else {
+				unhandledMessageReceived(m);
+			}
+		}
+
+		@Override
+		void processOFRoleReply(OFRoleReply m) {
+			roleChanger.deliverRoleReply(m.getXid(), m.getRole());
+		}
+
+		@Override
+		@LogMessageDoc(level="WARN",
+		message="Received PacketIn from switch {} while" +
+				"being slave. Reasserting slave role.",
+				explanation="The switch has receive a PacketIn despite being " +
+						"in slave role indicating inconsistent controller roles",
+						recommendation="This situation can occurs transiently during role" +
+								" changes. If, however, the condition persists or happens" +
+								" frequently this indicates a role inconsistency. " +
+								LogMessageDoc.CHECK_CONTROLLER )
+		void processOFPacketIn(OFPacketIn m) {
+			// we don't expect packetIn while slave, reassert we are slave
+			switchManagerCounters.packetInWhileSwitchIsSlave.increment();
+			log.warn("Received PacketIn from switch {} while" +
+					"being slave. Reasserting slave role.", sw);
+			reassertRole(OFControllerRole.ROLE_SLAVE);
+		}
+	};
+
+
+	/**
+	 * Create a new unconnected OFChannelHandler.
+	 * @param controller
+	 * @param broker
+	 * @throws SwitchHandshakeHandlerException
+	 */
+	OFSwitchHandshakeHandler(@Nonnull IOFConnectionBackend connection,
+			@Nonnull OFFeaturesReply featuresReply,
+			@Nonnull IOFSwitchManager switchManager,
+			@Nonnull RoleManager roleManager,
+			@Nonnull Timer timer) {
+		Preconditions.checkNotNull(connection, "connection");
+		Preconditions.checkNotNull(featuresReply, "featuresReply");
+		Preconditions.checkNotNull(switchManager, "switchManager");
+		Preconditions.checkNotNull(roleManager, "roleManager");
+		Preconditions.checkNotNull(timer, "timer");
+		Preconditions.checkArgument(connection.getAuxId().equals(OFAuxId.MAIN),
+				"connection must be MAIN connection but is %s", connection);
+
+		this.switchManager = switchManager;
+		this.roleManager = roleManager;
+		this.mainConnection = connection;
+		this.auxConnections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>();
+		this.featuresReply = featuresReply;
+		this.timer = timer;
+		this.switchManagerCounters = switchManager.getCounters();
+		this.factory = OFFactories.getFactory(featuresReply.getVersion());
+		this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_NS);
+		setState(new InitState());
+		this.pendingPortStatusMsg = new ArrayList<OFPortStatus>();
+
+		connection.setListener(this);
+	}
+
+	/**
+	 * This begins the switch handshake. We start where the OFChannelHandler
+	 * left off, right after receiving the OFFeaturesReply.
+	 */
+	public void beginHandshake() {
+		Preconditions.checkState(state instanceof InitState, "must be in InitState");
+
+		if (this.featuresReply.getNTables() > 1) {
+			log.debug("Have {} table(s) for switch {}", this.featuresReply.getNTables(),
+					getSwitchInfoString());
+		}
+
+		if (this.featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
+			setState(new WaitConfigReplyState());
+		} else {
+			// OF 1.3. Ask for Port Descriptions
+			setState(new WaitPortDescStatsReplyState());
+		}
+	}
+
+	public DatapathId getDpid(){
+		return this.featuresReply.getDatapathId();
+	}
+
+	public OFAuxId getOFAuxId(){
+		return this.featuresReply.getAuxiliaryId();
+	}
+
+	/**
+	 * Is this a state in which the handshake has completed?
+	 * @return true if the handshake is complete
+	 */
+	public boolean isHandshakeComplete() {
+		return this.state.isHandshakeComplete();
+	}
+
+	/**
+	 * Forwards to RoleChanger. See there.
+	 * @param role
+	 */
+	void sendRoleRequestIfNotPending(OFControllerRole role) {
+		try {
+			roleChanger.sendRoleRequestIfNotPending(role);
+		} catch (IOException e) {
+			log.error("Disconnecting switch {} due to IO Error: {}",
+					getSwitchInfoString(), e.getMessage());
+			mainConnection.disconnect();
+		}
+	}
+
+
+	/**
+	 * Forwards to RoleChanger. See there.
+	 * @param role
+	 */
+	void sendRoleRequest(OFControllerRole role) {
+		try {
+			roleChanger.sendRoleRequest(role);
+		} catch (IOException e) {
+			log.error("Disconnecting switch {} due to IO Error: {}",
+					getSwitchInfoString(), e.getMessage());
+			mainConnection.disconnect();
+		}
+	}
+
+	/**
+	 * Dispatches the message to the controller packet pipeline
+	 */
+	private void dispatchMessage(OFMessage m) {
+		this.switchManager.handleMessage(this.sw, m, null);
+	}
+
+	/**
+	 * Return a string describing this switch based on the already available
+	 * information (DPID and/or remote socket)
+	 * @return
+	 */
+	private String getSwitchInfoString() {
+		if (sw != null)
+			return sw.toString();
+		String channelString;
+		if (mainConnection == null || mainConnection.getRemoteInetAddress() == null) {
+			channelString = "?";
+		} else {
+			channelString = mainConnection.getRemoteInetAddress().toString();
+		}
+		String dpidString;
+		if (featuresReply == null) {
+			dpidString = "?";
+		} else {
+			dpidString = featuresReply.getDatapathId().toString();
+		}
+		return String.format("[%s DPID[%s]]", channelString, dpidString);
+	}
+
+	/**
+	 * Update the channels state. Only called from the state machine.
+	 * TODO: enforce restricted state transitions
+	 * @param state
+	 */
+	private void setState(OFSwitchHandshakeState state) {
+		this.state = state;
+		state.logState();
+		state.enterState();
+	}
+
+	public void processOFMessage(OFMessage m) {
+		state.processOFMessage(m);
+	}
+
+	/**
+	 * Send the configuration requests to tell the switch we want full
+	 * packets
+	 * @throws IOException
+	 */
+	private void sendHandshakeSetConfig() {
+		// Ensure we receive the full packet via PacketIn
+		// FIXME: We don't set the reassembly flags.
+		OFSetConfig configSet = factory.buildSetConfig()
+				.setXid(handshakeTransactionIds--)
+				.setMissSendLen(0xffff)
+				.build();
+
+		// Barrier
+		OFBarrierRequest barrier = factory.buildBarrierRequest()
+				.setXid(handshakeTransactionIds--)
+				.build();
+
+		// Verify (need barrier?)
+		OFGetConfigRequest configReq = factory.buildGetConfigRequest()
+				.setXid(handshakeTransactionIds--)
+				.build();
+		List<OFMessage> msgList = ImmutableList.<OFMessage>of(configSet, barrier, configReq);
+		mainConnection.write(msgList);
+	}
+
+	protected void sendPortDescRequest() {
+		mainConnection.write(factory.portDescStatsRequest(ImmutableSet.<OFStatsRequestFlags>of()));
+	}
+
+	/**
+	 * send a description state request
+	 */
+	private void sendHandshakeDescriptionStatsRequest() {
+		// Send description stats request to set switch-specific flags
+		OFDescStatsRequest descStatsRequest = factory.buildDescStatsRequest()
+				.setXid(handshakeTransactionIds--)
+				.build();
+		mainConnection.write(descStatsRequest);
+	}
+
+	OFSwitchHandshakeState getStateForTesting() {
+		return state;
+	}
+
+	void reassertRole(OFControllerRole role){
+		this.roleManager.reassertRole(this, HARole.ofOFRole(role));
+	}
+
+	void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) {
+		roleChanger = new RoleChanger(TimeUnit.MILLISECONDS.toNanos(roleTimeoutMs));
+	}
+
+	/**
+	 * Called by the switch manager when new aux connections have connected.
+	 * This alerts the state machine of an aux connection.
+	 *
+	 * @param connection
+	 *            the aux connection
+	 */
+	public synchronized void auxConnectionOpened(IOFConnectionBackend connection) {
+		if(log.isDebugEnabled())
+			log.debug("[{}] - Switch Handshake - new aux connection {}", this.getDpid(), connection.getAuxId());
+
+		// Handle new Auxiliary connections if the main connection has completed (i.e. in ACTIVE or STANDBY state)
+		if (this.getState().equals("ACTIVE") || this.getState().equals("STANDBY")) {
+			auxConnections.put(connection.getAuxId(), connection);
+			connection.setListener(OFSwitchHandshakeHandler.this);
+			log.info("Auxiliary connection {} added for {}.", connection.getAuxId().getValue(), connection.getDatapathId().toString());
+		} else {
+			log.info("Auxiliary connection {} initiated for {} before main connection handshake complete. Ignorning aux connection attempt.", connection.getAuxId().getValue(), connection.getDatapathId().toString());
+		}
+	}
+
+	/**
+	 * Gets the main connection
+	 *
+	 * @return the main connection
+	 */
+	public IOFConnectionBackend getMainConnection() {
+		return this.mainConnection;
+	}
+
+	/**
+	 * Determines if this handshake handler is responsible for the supplied
+	 * connection.
+	 *
+	 * @param connection
+	 *            an OF connection
+	 * @return true if the handler has the connection
+	 */
+	public boolean hasConnection(IOFConnectionBackend connection) {
+		if (this.mainConnection.equals(connection)
+				|| this.auxConnections.get(connection.getAuxId()) == connection) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	void cleanup() {
+		for (IOFConnectionBackend conn : this.auxConnections.values()) {
+			conn.disconnect();
+		}
+
+		this.mainConnection.disconnect();
+	}
+
+	public String getState() {
+		return this.state.getClass().getSimpleName();
+	}
+
+	public String getQuarantineReason() {
+		if(this.state instanceof QuarantineState) {
+			QuarantineState qs = (QuarantineState) this.state;
+			return qs.getQuarantineReason();
+		}
+		return null;
+	}
+
+	/**
+	 * Gets the current connections that this switch handshake handler is
+	 * responsible for. Used primarily by the REST API.
+	 * @return an immutable list of IOFConnections
+	 */
+	public ImmutableList<IOFConnection> getConnections() {
+		ImmutableList.Builder<IOFConnection> builder = ImmutableList.builder();
+
+		builder.add(mainConnection);
+		builder.addAll(auxConnections.values());
+
+		return builder.build();
+	}
+
+
+	/** IOFConnectionListener */
+	@Override
+	public void connectionClosed(IOFConnectionBackend connection) {
+		// Disconnect handler's remaining connections
+		cleanup();
+
+		// Only remove the switch handler when the main connection is
+		// closed
+		if (connection == this.mainConnection) {
+			switchManager.handshakeDisconnected(connection.getDatapathId());
+			if(sw != null) {
+				log.debug("[{}] - main connection {} closed - disconnecting switch",
+						connection);
+
+				setSwitchStatus(SwitchStatus.DISCONNECTED);
+				switchManager.switchDisconnected(sw);
+			}
+		}
+	}
+
+	@Override
+	public void messageReceived(IOFConnectionBackend connection, OFMessage m) {
+		processOFMessage(m);
+	}
+
+	@Override
+	public boolean isSwitchHandshakeComplete(IOFConnectionBackend connection) {
+		return state.isHandshakeComplete();
+	}
+
+	public void setSwitchStatus(SwitchStatus status) {
+		if(sw != null) {
+			SwitchStatus oldStatus = sw.getStatus();
+			if(oldStatus != status) {
+				log.debug("[{}] SwitchStatus change to {} requested, switch is in status " + oldStatus,
+						mainConnection.getDatapathId(), status);
+				sw.setStatus(status);
+				switchManager.switchStatusChanged(sw, oldStatus, status);
+			} else {
+				log.warn("[{}] SwitchStatus change to {} requested, switch is already in status",
+						mainConnection.getDatapathId(), status);
+			}
+		} else {
+			log.warn("[{}] SwitchStatus change to {} requested, but switch is not allocated yet",
+					mainConnection.getDatapathId(), status);
+		}
+	}
 
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
index 46d90645c..09468075d 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
@@ -381,8 +381,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 	 * It is needed for the rest of the switch handshake.
 	 */
 	@Override
-	public void connectionOpened(IOFConnectionBackend connection,
-			OFFeaturesReply featuresReply) {
+	public void connectionOpened(IOFConnectionBackend connection, OFFeaturesReply featuresReply) {
 		DatapathId dpid = connection.getDatapathId();
 		OFAuxId auxId = connection.getAuxId();
 
diff --git a/src/main/java/net/floodlightcontroller/hub/Hub.java b/src/main/java/net/floodlightcontroller/hub/Hub.java
index 5de64574d..d2fceca29 100644
--- a/src/main/java/net/floodlightcontroller/hub/Hub.java
+++ b/src/main/java/net/floodlightcontroller/hub/Hub.java
@@ -32,6 +32,8 @@ import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 
 import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFlowAdd;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPacketIn;
 import org.projectfloodlight.openflow.protocol.OFPacketOut;
@@ -39,12 +41,15 @@ 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.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.match.Match;
 import org.projectfloodlight.openflow.protocol.match.MatchField;
 import org.projectfloodlight.openflow.types.OFBufferId;
 import org.projectfloodlight.openflow.types.OFPort;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import sun.awt.OrientableFlowLayout;
+
 /**
  *
  * @author David Erickson (daviderickson@cs.stanford.edu) - 04/04/10
@@ -67,7 +72,33 @@ public class Hub implements IFloodlightModule, IOFMessageListener {
     }
 
     public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        OFPacketIn pi = (OFPacketIn) msg;
+        //OFMessage outMessage = createHubPacketOut(sw, msg);
+        OFMessage outMessage = createHubFlowMod(sw, msg);
+        sw.write(outMessage);
+
+        return Command.CONTINUE;
+    }
+    
+    private OFMessage createHubFlowMod(IOFSwitch sw, OFMessage msg) {
+    	OFPacketIn pi = (OFPacketIn) msg;
+        OFFlowAdd.Builder fmb = /*sw.getOFFactory()*/OFFactories.getFactory(OFVersion.OF_13).buildFlowAdd();
+        //Match.Builder mb = OFFactories.getFactory(OFVersion.OF_13).buildMatch();
+        
+        fmb.setBufferId(pi.getBufferId())
+        .setXid(pi.getXid())
+        /*.setMatch(pi.getMatch())*/;
+
+        // set actions
+        OFActionOutput.Builder actionBuilder = /*sw.getOFFactory()*/OFFactories.getFactory(OFVersion.OF_13).actions().buildOutput();
+        actionBuilder.setPort(OFPort.ALL);
+        fmb.setActions(Collections.singletonList((OFAction) actionBuilder.build()));
+        fmb.setOutPort(OFPort.ALL);
+
+        return fmb.build();
+    }
+    
+    private OFMessage createHubPacketOut(IOFSwitch sw, OFMessage msg) {
+    	OFPacketIn pi = (OFPacketIn) msg;
         OFPacketOut.Builder pob = /*sw.getOFFactory()*/OFFactories.getFactory(OFVersion.OF_13).buildPacketOut();
         pob.setBufferId(pi.getBufferId()).setXid(pi.getXid()).setInPort(pi.getMatch().get(MatchField.IN_PORT));
 
@@ -81,9 +112,7 @@ public class Hub implements IFloodlightModule, IOFMessageListener {
             byte[] packetData = pi.getData();
             pob.setData(packetData);
         }
-        sw.write(pob.build());
-
-        return Command.CONTINUE;
+        return pob.build();  	
     }
 
     @Override
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java b/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java
index efa4321b5..22b60197b 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/IStaticFlowEntryPusherService.java
@@ -30,7 +30,7 @@ public interface IStaticFlowEntryPusherService extends IFloodlightService {
      * @param fm The flow to push.
      * @param swDpid The switch DPID to push it to, in 00:00:00:00:00:00:00:01 notation.
      */
-    public void addFlow(String name, OFFlowMod fm, String swDpid);
+    public void addFlow(String name, OFFlowMod fm, DatapathId swDpid);
     
     /**
      * Deletes a static flow
@@ -57,6 +57,6 @@ public interface IStaticFlowEntryPusherService extends IFloodlightService {
     /**
      * Gets a list of flows by switch
      */
-    public Map<String, OFFlowMod> getFlows(String dpid);
+    public Map<String, OFFlowMod> getFlows(DatapathId dpid);
 
 }
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java
index 96bba96e6..f217b5c7f 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java
@@ -165,49 +165,50 @@ public class StaticFlowEntries {
         if ((fm.getActions() != null) && (fm.getActions().size() > 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_ACTIONS, StaticFlowEntries.flowModActionsToString(fm.getActions()));
         
-        if (match.get(MatchField.IN_PORT).getPortNumber() != 0)
+        if ((match.get(MatchField.IN_PORT) != null) && (match.get(MatchField.IN_PORT).getPortNumber() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_IN_PORT, Integer.toString(match.get(MatchField.IN_PORT).getPortNumber()));
         
-        if (!match.get(MatchField.ETH_SRC).equals(MacAddress.of(0)))
+        if ((match.get(MatchField.ETH_SRC) != null) && !match.get(MatchField.ETH_SRC).equals(MacAddress.of(0)))
         	entry.put(StaticFlowEntryPusher.COLUMN_DL_SRC, match.get(MatchField.ETH_SRC).toString());
 
-        if (!match.get(MatchField.ETH_DST).equals(MacAddress.of(0)))
+        if ((match.get(MatchField.ETH_DST) != null) && !match.get(MatchField.ETH_DST).equals(MacAddress.of(0)))
         	entry.put(StaticFlowEntryPusher.COLUMN_DL_DST, match.get(MatchField.ETH_DST).toString());
         
-        if (match.get(MatchField.VLAN_VID).getVlan() != -1)
+        if ((match.get(MatchField.VLAN_VID) != null) && (match.get(MatchField.VLAN_VID).getVlan() != -1))
         	entry.put(StaticFlowEntryPusher.COLUMN_DL_VLAN, match.get(MatchField.VLAN_VID).toString());
         
-        if (match.get(MatchField.VLAN_PCP).getValue() != 0)
+        if ((match.get(MatchField.VLAN_PCP) != null) && (match.get(MatchField.VLAN_PCP).getValue() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_DL_VLAN_PCP, Byte.toString(match.get(MatchField.VLAN_PCP).getValue()));
         
-        if (match.get(MatchField.ETH_TYPE).getValue() != 0)
+        if ((match.get(MatchField.ETH_TYPE) != null) && (match.get(MatchField.ETH_TYPE).getValue() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_DL_TYPE, match.get(MatchField.ETH_TYPE).toString());
         
-        if (match.get(MatchField.IP_ECN).getEcnValue() != 0 && match.get(MatchField.IP_DSCP).getDscpValue() != 0)
+        if ((match.get(MatchField.IP_ECN) != null) && (match.get(MatchField.IP_DSCP) != null) 
+        		&& (match.get(MatchField.IP_ECN).getEcnValue() != 0) && (match.get(MatchField.IP_DSCP).getDscpValue() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_NW_TOS, // TOS = [DSCP bits 0-5] + [ECN bits 6-7] --> bitwise OR to get TOS byte
         			Byte.toString((byte) (match.get(MatchField.IP_ECN).getEcnValue() | match.get(MatchField.IP_DSCP).getDscpValue())));
         
-        if (match.get(MatchField.IP_PROTO).getIpProtocolNumber() != 0)
+        if ((match.get(MatchField.IP_PROTO) != null) && (match.get(MatchField.IP_PROTO).getIpProtocolNumber() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_NW_PROTO, Short.toString(match.get(MatchField.IP_PROTO).getIpProtocolNumber()));
         
-        if (match.get(MatchField.IPV4_SRC).getInt() != 0)
+        if ((match.get(MatchField.IPV4_SRC) != null) && (match.get(MatchField.IPV4_SRC).getInt() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_NW_SRC, match.get(MatchField.IPV4_SRC).toString());
         
-        if (match.get(MatchField.IPV4_DST).getInt() != 0)
+        if ((match.get(MatchField.IPV4_DST) != null) && (match.get(MatchField.IPV4_DST).getInt() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_NW_DST, match.get(MatchField.IPV4_DST).toString());
         
-        if (match.get(MatchField.TCP_SRC).getPort() != 0)
+        if ((match.get(MatchField.TCP_SRC) != null) && (match.get(MatchField.TCP_SRC).getPort() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_TP_SRC, match.get(MatchField.TCP_SRC).toString());
-        else if (match.get(MatchField.UDP_SRC).getPort() != 0)
+        else if ((match.get(MatchField.UDP_SRC) != null) && (match.get(MatchField.UDP_SRC).getPort() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_TP_SRC, match.get(MatchField.UDP_SRC).toString());
-        else if (match.get(MatchField.SCTP_SRC).getPort() != 0)
+        else if ((match.get(MatchField.SCTP_SRC) != null) && (match.get(MatchField.SCTP_SRC).getPort() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_TP_SRC, match.get(MatchField.SCTP_SRC).toString());
         
-        if (match.get(MatchField.TCP_DST).getPort() != 0)
+        if ((match.get(MatchField.TCP_DST) != null) && (match.get(MatchField.TCP_DST).getPort() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_TP_DST, match.get(MatchField.TCP_DST).toString());
-        else if (match.get(MatchField.UDP_DST).getPort() != 0)
+        else if ((match.get(MatchField.UDP_DST) != null) && (match.get(MatchField.UDP_DST).getPort() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_TP_SRC, match.get(MatchField.UDP_DST).toString());
-        else if (match.get(MatchField.SCTP_DST).getPort() != 0)
+        else if ((match.get(MatchField.SCTP_DST) != null) && (match.get(MatchField.SCTP_DST).getPort() != 0))
         	entry.put(StaticFlowEntryPusher.COLUMN_TP_SRC, match.get(MatchField.SCTP_DST).toString());
         
         return entry;
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
index c9a9e5eff..9276da296 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
@@ -50,12 +50,12 @@ import net.floodlightcontroller.storage.IResultSet;
 import net.floodlightcontroller.storage.IStorageSourceListener;
 import net.floodlightcontroller.storage.IStorageSourceService;
 import net.floodlightcontroller.storage.StorageException;
+import net.floodlightcontroller.util.FlowModUtils;
 import net.floodlightcontroller.util.MatchString;
 
 import org.projectfloodlight.openflow.protocol.OFFactories;
 import org.projectfloodlight.openflow.protocol.OFFlowDeleteStrict;
 import org.projectfloodlight.openflow.protocol.OFFlowMod;
-import org.projectfloodlight.openflow.protocol.OFFlowModifyStrict;
 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
 import org.projectfloodlight.openflow.protocol.OFFlowRemovedReason;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
@@ -75,8 +75,7 @@ import org.slf4j.LoggerFactory;
  * is responsible for ensuring they make sense for the network.
  */
 public class StaticFlowEntryPusher
-implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
-IStorageSourceListener, IOFMessageListener {
+implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, IStorageSourceListener, IOFMessageListener {
 	protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusher.class);
 	public static final String StaticFlowName = "staticflowentry";
 
@@ -397,22 +396,21 @@ IStorageSourceListener, IOFMessageListener {
 
 			List<OFMessage> outQueue = new ArrayList<OFMessage>();
 			for (String entry : entriesToAdd.get(dpid).keySet()) {
-				OFFlowModifyStrict newFlowMod = (OFFlowModifyStrict) entriesToAdd.get(dpid).get(entry); //TODO @Ryan cast valid?
-				//OFFlowMod oldFlowMod = entriesFromStorage.get(dpid).get(entry);
-				OFFlowDeleteStrict oldFlowMod = null;
+				OFFlowMod newFlowMod = entriesToAdd.get(dpid).get(entry);
+				OFFlowMod oldFlowMod = null;
 				String dpidOldFlowMod = entry2dpid.get(entry);
 				if (dpidOldFlowMod != null) {
-					oldFlowMod = (OFFlowDeleteStrict) entriesFromStorage.get(dpidOldFlowMod).remove(entry); //TODO @Ryan cast valid?
+					oldFlowMod = entriesFromStorage.get(dpidOldFlowMod).remove(entry);
 				}
 				if (oldFlowMod != null && newFlowMod != null) {
 					// set the new flow mod to modify a pre-existing rule if these fields match
 					if (oldFlowMod.getMatch().equals(newFlowMod.getMatch())
 							&& oldFlowMod.getCookie() == newFlowMod.getCookie()
 							&& oldFlowMod.getPriority() == newFlowMod.getPriority()) {
-						//newFlowMod = newFlowMod.createBuilder().setCommand(OFFlowModCommand.MODIFY_STRICT).build();
+						newFlowMod = FlowModUtils.toFlowModifyStrict(newFlowMod);
 						// if they don't match delete the old flow
 					} else {
-						//oldFlowMod.createBuilder().setCommand(OFFlowModCommand.DELETE_STRICT);
+						oldFlowMod = FlowModUtils.toFlowDeleteStrict(oldFlowMod);
 						if (dpidOldFlowMod.equals(dpid)) {
 							outQueue.add(oldFlowMod);
 						} else {
@@ -468,15 +466,12 @@ IStorageSourceListener, IOFMessageListener {
 		}
 
 		// send flow_mod delete
-		OFFlowDeleteStrict flowMod = (OFFlowDeleteStrict) entriesFromStorage.get(dpid).get(entryName); //TODO @Ryan can this be cast?
-		//flowMod.createBuilder().setCommand(OFFlowModCommand.DELETE_STRICT); // can't find a way to set command
+		OFFlowDeleteStrict flowMod = FlowModUtils.toFlowDeleteStrict(entriesFromStorage.get(dpid).get(entryName));
 
-		if (entriesFromStorage.containsKey(dpid) &&
-				entriesFromStorage.get(dpid).containsKey(entryName)) {
+		if (entriesFromStorage.containsKey(dpid) && entriesFromStorage.get(dpid).containsKey(entryName)) {
 			entriesFromStorage.get(dpid).remove(entryName);
 		} else {
-			log.debug("Tried to delete non-existent entry {} for switch {}",
-					entryName, dpid);
+			log.debug("Tried to delete non-existent entry {} for switch {}", entryName, dpid);
 			return;
 		}
 
@@ -500,7 +495,7 @@ IStorageSourceListener, IOFMessageListener {
 			if (log.isDebugEnabled()) {
 				log.debug("Sending {} new entries to {}", messages.size(), dpid);
 			}
-			ofswitch.write(messages, null);
+			ofswitch.write(messages);
 			ofswitch.flush();
 		}
 	}
@@ -521,7 +516,7 @@ IStorageSourceListener, IOFMessageListener {
 			if (log.isDebugEnabled()) {
 				log.debug("Sending 1 new entries to {}", dpid.toString());
 			}
-			ofswitch.write(message, null);
+			ofswitch.write(message);
 			ofswitch.flush();
 		}
 	}
@@ -536,8 +531,7 @@ IStorageSourceListener, IOFMessageListener {
 		IOFSwitch ofSwitch = switchService.getSwitch(dpid);
 		if (ofSwitch == null) {
 			if (log.isDebugEnabled()) {
-				log.debug("Not deleting key {} :: switch {} not connected",
-						dpid.toString());
+				log.debug("Not deleting key {} :: switch {} not connected", dpid.toString());
 			}
 			return;
 		}
@@ -555,7 +549,7 @@ IStorageSourceListener, IOFMessageListener {
 					"static flow to a switch",
 					recommendation=LogMessageDoc.CHECK_SWITCH)
 	private void writeFlowModToSwitch(IOFSwitch sw, OFFlowMod flowMod) {
-		sw.write(flowMod, null);
+		sw.write(flowMod);
 		sw.flush();
 	}
 
@@ -678,8 +672,8 @@ IStorageSourceListener, IOFMessageListener {
 	// IStaticFlowEntryPusherService methods
 
 	@Override
-	public void addFlow(String name, OFFlowMod fm, String swDpid) {
-		Map<String, Object> fmMap = StaticFlowEntries.flowModToStorageEntry(fm, swDpid, name);
+	public void addFlow(String name, OFFlowMod fm, DatapathId swDpid) {
+		Map<String, Object> fmMap = StaticFlowEntries.flowModToStorageEntry(fm, swDpid.toString(), name);
 		storageSourceService.insertRowAsync(TABLE_NAME, fmMap);
 	}
 
@@ -803,8 +797,8 @@ IStorageSourceListener, IOFMessageListener {
 	}
 
 	@Override
-	public Map<String, OFFlowMod> getFlows(String dpid) {
-		return entriesFromStorage.get(dpid);
+	public Map<String, OFFlowMod> getFlows(DatapathId dpid) {
+		return entriesFromStorage.get(dpid.toString());
 	}
 
 	// IHAListener
@@ -834,21 +828,19 @@ IStorageSourceListener, IOFMessageListener {
 		@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 transitionToStandby() {
-			// TODO Auto-generated method stub
-			
+		public void transitionToStandby() {	
+			log.debug("Controller is now in STANDBY role. Clearing static flow entries from store.");
+			deleteAllFlows();
 		}
 	}
 }
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/web/ListStaticFlowEntriesResource.java b/src/main/java/net/floodlightcontroller/staticflowentry/web/ListStaticFlowEntriesResource.java
index 617088b14..37a39bc86 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/web/ListStaticFlowEntriesResource.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/web/ListStaticFlowEntriesResource.java
@@ -23,6 +23,7 @@ import net.floodlightcontroller.core.web.ControllerSwitchesResource;
 import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService;
 
 import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.types.DatapathId;
 import org.restlet.data.Status;
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
@@ -48,7 +49,7 @@ public class ListStaticFlowEntriesResource extends ServerResource {
             try {
                 Map<String, Map<String, OFFlowMod>> retMap = 
                         new HashMap<String, Map<String, OFFlowMod>>();
-                retMap.put(param, sfpService.getFlows(param));
+                retMap.put(param, sfpService.getFlows(DatapathId.of(param)));
                 return retMap;
                 
             } catch (NumberFormatException e){
diff --git a/src/main/java/net/floodlightcontroller/testmodule/TestModule.java b/src/main/java/net/floodlightcontroller/testmodule/TestModule.java
new file mode 100644
index 000000000..b3f27794d
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/testmodule/TestModule.java
@@ -0,0 +1,81 @@
+package net.floodlightcontroller.testmodule;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.staticflowentry.IStaticFlowEntryPusherService;
+
+public class TestModule implements IFloodlightModule {
+
+	private static IStaticFlowEntryPusherService sfps;
+	protected static Logger log;
+	
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+		return null;
+	}
+
+	@Override
+	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+		return null;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IStaticFlowEntryPusherService.class);
+		return l;
+	}
+
+	@Override
+	public void init(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+		sfps = context.getServiceImpl(IStaticFlowEntryPusherService.class);
+		log = LoggerFactory.getLogger(TestModule.class);
+		if (sfps == null) {
+			log.error("Static Flow Pusher Service not found!");
+		}
+	}
+
+	@Override
+	public void startUp(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+		OFFlowMod.Builder fmb = OFFactories.getFactory(OFVersion.OF_13).buildFlowModify();
+		OFActionOutput.Builder aob = OFFactories.getFactory(OFVersion.OF_13).actions().buildOutput();
+		List<OFAction> al = new ArrayList<OFAction>();
+		al.add(aob.setPort(OFPort.ALL).build());
+		fmb.setActions(al);
+		fmb.setBufferId(OFBufferId.NO_BUFFER);
+		fmb.setIdleTimeout(10);
+		fmb.setHardTimeout(60);
+		fmb.setOutPort(OFPort.ALL); // let's try and mimic the hub module, but with a flow instead
+									// is this really necessary with the OFOutputAction explicitly set?
+		
+		// we aren't matching anything specifically, so all should be wildcarded by default
+		// in on any port, with any header attributes, send out all ports = Hub module
+		try {
+			Thread.sleep(3000);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+		sfps.addFlow("test-flow", fmb.build(), DatapathId.of(1)); // This should add the flow, regardless whether or not the switch is connected, I believe. If it connects in a second, it should be pushed.
+	}
+
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowModUtils.java b/src/main/java/net/floodlightcontroller/util/FlowModUtils.java
new file mode 100644
index 000000000..bd17cafdd
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowModUtils.java
@@ -0,0 +1,119 @@
+package net.floodlightcontroller.util;
+
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFlowAdd;
+import org.projectfloodlight.openflow.protocol.OFFlowDelete;
+import org.projectfloodlight.openflow.protocol.OFFlowDeleteStrict;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowModify;
+import org.projectfloodlight.openflow.protocol.OFFlowModifyStrict;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+/**
+ * Convert an OFFlowMod to a specific OFFlowMod-OFFlowModCommand.
+ * These function as setCommand(OFFlowModCommand) methods for an OFFlowMod.
+ * Used initially in the static flow pusher, but will likely find merit elsewhere.
+ *
+ * @author Ryan Izard <ryan.izard@bigswitch.com, rizard@g.clemson.edu>
+ */
+public class FlowModUtils {
+	public static OFFlowAdd toFlowAdd(OFFlowMod fm) {
+		OFVersion version = fm.getVersion();
+		OFFlowAdd.Builder b = OFFactories.getFactory(version).buildFlowAdd();
+		return b.setActions(fm.getActions())
+				.setBufferId(fm.getBufferId())
+				.setCookie(fm.getCookie())
+				.setCookieMask(fm.getCookieMask())
+				.setFlags(fm.getFlags())
+				.setHardTimeout(fm.getHardTimeout())
+				.setIdleTimeout(fm.getIdleTimeout())
+				.setInstructions(fm.getInstructions())
+				.setMatch(fm.getMatch())
+				.setOutGroup(fm.getOutGroup())
+				.setOutPort(fm.getOutPort())
+				.setPriority(fm.getPriority())
+				.setTableId(fm.getTableId())
+				.setXid(fm.getXid())
+				.build();
+	}
+
+	public static OFFlowDelete toFlowDelete(OFFlowMod fm) {
+		OFVersion version = fm.getVersion();
+		OFFlowDelete.Builder b = OFFactories.getFactory(version).buildFlowDelete();
+		return b.setActions(fm.getActions())
+				.setBufferId(fm.getBufferId())
+				.setCookie(fm.getCookie())
+				.setCookieMask(fm.getCookieMask())
+				.setFlags(fm.getFlags())
+				.setHardTimeout(fm.getHardTimeout())
+				.setIdleTimeout(fm.getIdleTimeout())
+				.setInstructions(fm.getInstructions())
+				.setMatch(fm.getMatch())
+				.setOutGroup(fm.getOutGroup())
+				.setOutPort(fm.getOutPort())
+				.setPriority(fm.getPriority())
+				.setTableId(fm.getTableId())
+				.setXid(fm.getXid())
+				.build();
+	}
+
+	public static OFFlowDeleteStrict toFlowDeleteStrict(OFFlowMod fm) {
+		OFVersion version = fm.getVersion();
+		OFFlowDeleteStrict.Builder b = OFFactories.getFactory(version).buildFlowDeleteStrict();
+		return b.setActions(fm.getActions())
+				.setBufferId(fm.getBufferId())
+				.setCookie(fm.getCookie())
+				.setCookieMask(fm.getCookieMask())
+				.setFlags(fm.getFlags())
+				.setHardTimeout(fm.getHardTimeout())
+				.setIdleTimeout(fm.getIdleTimeout())
+				.setInstructions(fm.getInstructions())
+				.setMatch(fm.getMatch())
+				.setOutGroup(fm.getOutGroup())
+				.setOutPort(fm.getOutPort())
+				.setPriority(fm.getPriority())
+				.setTableId(fm.getTableId())
+				.setXid(fm.getXid())
+				.build();
+	}
+
+	public static OFFlowModify toFlowModify(OFFlowMod fm) {
+		OFVersion version = fm.getVersion();
+		OFFlowModify.Builder b = OFFactories.getFactory(version).buildFlowModify();
+		return b.setActions(fm.getActions())
+				.setBufferId(fm.getBufferId())
+				.setCookie(fm.getCookie())
+				.setCookieMask(fm.getCookieMask())
+				.setFlags(fm.getFlags())
+				.setHardTimeout(fm.getHardTimeout())
+				.setIdleTimeout(fm.getIdleTimeout())
+				.setInstructions(fm.getInstructions())
+				.setMatch(fm.getMatch())
+				.setOutGroup(fm.getOutGroup())
+				.setOutPort(fm.getOutPort())
+				.setPriority(fm.getPriority())
+				.setTableId(fm.getTableId())
+				.setXid(fm.getXid())
+				.build();
+	}
+
+	public static OFFlowModifyStrict toFlowModifyStrict(OFFlowMod fm) {
+		OFVersion version = fm.getVersion();
+		OFFlowModifyStrict.Builder b = OFFactories.getFactory(version).buildFlowModifyStrict();
+		return b.setActions(fm.getActions())
+				.setBufferId(fm.getBufferId())
+				.setCookie(fm.getCookie())
+				.setCookieMask(fm.getCookieMask())
+				.setFlags(fm.getFlags())
+				.setHardTimeout(fm.getHardTimeout())
+				.setIdleTimeout(fm.getIdleTimeout())
+				.setInstructions(fm.getInstructions())
+				.setMatch(fm.getMatch())
+				.setOutGroup(fm.getOutGroup())
+				.setOutPort(fm.getOutPort())
+				.setPriority(fm.getPriority())
+				.setTableId(fm.getTableId())
+				.setXid(fm.getXid())
+				.build();
+	}
+}
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index dd3bbfd31..673c92bd2 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -16,4 +16,6 @@ net.floodlightcontroller.threadpool.ThreadPool
 net.floodlightcontroller.core.internal.ShutdownServiceImpl
 org.sdnplatform.sync.internal.SyncManager
 org.sdnplatform.sync.internal.SyncTorture
-net.floodlightcontroller.hub.Hub
\ No newline at end of file
+net.floodlightcontroller.hub.Hub
+net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher
+net.floodlightcontroller.testmodule.TestModule
\ No newline at end of file
diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties
index 1f4417232..c54c7b5c2 100644
--- a/src/main/resources/floodlightdefault.properties
+++ b/src/main/resources/floodlightdefault.properties
@@ -7,8 +7,9 @@ net.floodlightcontroller.debugcounter.DebugCounterServiceImpl,\
 net.floodlightcontroller.restserver.RestApiServer,\
 net.floodlightcontroller.perfmon.PktInProcessingTime,\
 net.floodlightcontroller.hub.Hub,\
-net.floodlightcontroller.debugevent.DebugEventService
+net.floodlightcontroller.debugevent.DebugEventService,\
+net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher
 org.sdnplatform.sync.internal.SyncManager.authScheme=CHALLENGE_RESPONSE
 org.sdnplatform.sync.internal.SyncManager.keyStorePath=/etc/floodlight/auth_credentials.jceks
 org.sdnplatform.sync.internal.SyncManager.dbPath=/var/lib/floodlight/
-net.floodlightcontroller.core.internal.FloodlightProvider.role=MASTER
+net.floodlightcontroller.core.internal.FloodlightProvider.role=ACTIVE
-- 
GitLab