splitting roles from IO loop and providing a abstract of switch
diff --git a/of/api/pom.xml b/of/api/pom.xml
index 8f123e1..050fedd 100644
--- a/of/api/pom.xml
+++ b/of/api/pom.xml
@@ -63,7 +63,7 @@
                 <configuration>
                     <instructions>
                         <Export-Package>
-                            org.projectfloodlight.openflow.*
+                            org.onlab.onos.of.*,org.projectfloodlight.openflow.*
                         </Export-Package>
                     </instructions>
                 </configuration>
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/DeleteMe.java b/of/api/src/main/java/org/onlab/onos/of/controller/DeleteMe.java
deleted file mode 100644
index 1db6eae..0000000
--- a/of/api/src/main/java/org/onlab/onos/of/controller/DeleteMe.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.onlab.onos.of.controller;
-
-/**
- * Created by tom on 8/21/14.
- */
-public interface DeleteMe {
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/Dpid.java b/of/api/src/main/java/org/onlab/onos/of/controller/Dpid.java
similarity index 96%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/Dpid.java
rename to of/api/src/main/java/org/onlab/onos/of/controller/Dpid.java
index dec8424..02a957e 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/Dpid.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/Dpid.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.of.controller.impl.util;
+package org.onlab.onos.of.controller;
 
 import org.projectfloodlight.openflow.util.HexString;
 
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowController.java b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowController.java
new file mode 100644
index 0000000..5aec885
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowController.java
@@ -0,0 +1,100 @@
+package org.onlab.onos.of.controller;
+
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+/**
+ * Abstraction of an OpenFlow controller. Serves as a one stop
+ * shop for obtaining OpenFlow devices and (un)register listeners
+ * on OpenFlow events
+ */
+public interface OpenFlowController {
+
+    /**
+     * Returns all switches known to this OF controller.
+     * @return Iterable of dpid elements
+     */
+    public Iterable<OpenFlowSwitch> getSwitches();
+
+    /**
+     * Returns all master switches known to this OF controller.
+     * @return Iterable of dpid elements
+     */
+    public Iterable<OpenFlowSwitch> getMasterSwitches();
+
+    /**
+     * Returns all equal switches known to this OF controller.
+     * @return Iterable of dpid elements
+     */
+    public Iterable<OpenFlowSwitch> getEqualSwitches();
+
+
+    /**
+     * Returns the actual switch for the given Dpid.
+     * @param dpid the switch to fetch
+     * @return the interface to this switch
+     */
+    public OpenFlowSwitch getSwitch(Dpid dpid);
+
+    /**
+     * Returns the actual master switch for the given Dpid, if one exists.
+     * @param dpid the switch to fetch
+     * @return the interface to this switch
+     */
+    public OpenFlowSwitch getMasterSwitch(Dpid dpid);
+
+    /**
+     * Returns the actual equal switch for the given Dpid, if one exists.
+     * @param dpid the switch to fetch
+     * @return the interface to this switch
+     */
+    public OpenFlowSwitch getEqualSwitch(Dpid dpid);
+
+    /**
+     * Register a listener for meta events that occur to OF
+     * devices.
+     * @param listener the listener to notify
+     */
+    public void addListener(OpenFlowSwitchListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to unregister
+     */
+    public void removeListener(OpenFlowSwitchListener listener);
+
+    /**
+     * Register a listener for packet events.
+     * @param priority the importance of this listener, lower values are more important
+     * @param listener the listener to notify
+     */
+    public void addPacketListener(int priority, PacketListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to unregister
+     */
+    public void removePacketListener(PacketListener listener);
+
+    /**
+     * Send a message to a particular switch.
+     * @param dpid the switch to send to.
+     * @param msg the message to send
+     */
+    public void write(Dpid dpid, OFMessage msg);
+
+    /**
+     * Process a message and notify the appropriate listeners.
+     *
+     * @param msg the message to process.
+     */
+    public void processPacket(OFMessage msg);
+
+    /**
+     * Sets the role for a given switch.
+     * @param role the desired role
+     * @param dpid the switch to set the role for.
+     */
+    public void setRole(Dpid dpid, RoleState role);
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java
new file mode 100644
index 0000000..e6f52bd
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java
@@ -0,0 +1,23 @@
+package org.onlab.onos.of.controller;
+
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+/**
+ * Abstract model of an OpenFlow Switch.
+ *
+ */
+public interface OpenFlowSwitch {
+
+    /**
+     * Writes the message to this switch.
+     *
+     * @param msg the message to write
+     */
+    public void write(OFMessage msg);
+
+    /**
+     * Handle a message from the switch.
+     * @param fromSwitch the message to handle
+     */
+    public void handleMessage(OFMessage fromSwitch);
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchEvent.java b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchEvent.java
new file mode 100644
index 0000000..281d505
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchEvent.java
@@ -0,0 +1,17 @@
+package org.onlab.onos.of.controller;
+
+/**
+ * Meta events that can happen at a switch.
+ *
+ */
+public enum OpenFlowSwitchEvent {
+    /**
+     * The switch connected.
+     */
+    SWITCH_CONNECTED,
+
+    /**
+     * The switch disconnected.
+     */
+    SWITCH_DISCONNECTED
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchListener.java b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchListener.java
new file mode 100644
index 0000000..7ccba6d
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchListener.java
@@ -0,0 +1,20 @@
+package org.onlab.onos.of.controller;
+
+/**
+ * Allows for providers interested in Switch events to be notified.
+ */
+public interface OpenFlowSwitchListener {
+
+    /**
+     * Notify that the switch was added.
+     * @param dpid the switch where the event occurred
+     */
+    public void switchAdded(Dpid dpid);
+
+    /**
+     * Notify that the switch was removed.
+     * @param dpid the switch where the event occurred.
+     */
+    public void switchRemoved(Dpid dpid);
+
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/PacketContext.java b/of/api/src/main/java/org/onlab/onos/of/controller/PacketContext.java
new file mode 100644
index 0000000..bc06e93
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/PacketContext.java
@@ -0,0 +1,50 @@
+package org.onlab.onos.of.controller;
+
+import org.projectfloodlight.openflow.types.OFPort;
+
+/**
+ * A representation of a packet context which allows any provider
+ * to view the packet in event but may block the response to the
+ * event if blocked has been called.
+ */
+public interface PacketContext {
+
+    //TODO: may want to support sending packet out other switches than
+    // the one it came in on.
+    /**
+     * Blocks further responses (ie. send() calls) on this
+     * packet in event.
+     */
+    public void block();
+
+    /**
+     * Provided build has been called send the packet
+     * out the switch it came in on.
+     */
+    public void send();
+
+    /**
+     * Build the packet out in response to this packet in event.
+     * @param outPort the out port to send to packet out of.
+     */
+    public void build(OFPort outPort);
+
+    /**
+     * Build the packet out in response to this packet in event.
+     * @param ethFrame the actual packet to send out.
+     * @param outPort the out port to send to packet out of.
+     */
+    public void build(Object ethFrame, OFPort outPort);
+
+    /**
+     * Provided a handle onto the parsed payload.
+     * @return the parsed form of the payload.
+     */
+    public Object parsed();
+
+    /**
+     * Provide the dpid of the switch where the packet in arrived.
+     * @return the dpid of the switch.
+     */
+    public Dpid dpid();
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/PacketListener.java b/of/api/src/main/java/org/onlab/onos/of/controller/PacketListener.java
new file mode 100644
index 0000000..5c6d73f
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/PacketListener.java
@@ -0,0 +1,13 @@
+package org.onlab.onos.of.controller;
+
+/**
+ * Notifies providers about Packet in events.
+ */
+public interface PacketListener {
+
+    /**
+     * Handle the packet.
+     * @param pktCtx the packet context ({@link }
+     */
+    public void handlePacket(PacketContext pktCtx);
+}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/RoleState.java b/of/api/src/main/java/org/onlab/onos/of/controller/RoleState.java
new file mode 100644
index 0000000..527a91c
--- /dev/null
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/RoleState.java
@@ -0,0 +1,23 @@
+package org.onlab.onos.of.controller;
+
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+
+/**
+ * The role of the controller as it pertains to a particular switch.
+ * Note that this definition of the role enum is different from the
+ * OF1.3 definition. It is maintained here to be backward compatible to
+ * earlier versions of the controller code. This enum is translated
+ * to the OF1.3 enum, before role messages are sent to the switch.
+ * See sendRoleRequestMessage method in OFSwitchImpl
+ */
+public enum RoleState {
+    EQUAL(OFControllerRole.ROLE_EQUAL),
+    MASTER(OFControllerRole.ROLE_MASTER),
+    SLAVE(OFControllerRole.ROLE_SLAVE);
+
+    private RoleState(OFControllerRole nxRole) {
+        nxRole.ordinal();
+    }
+
+}
+
diff --git a/of/ctl/pom.xml b/of/ctl/pom.xml
index 5c090cb..88bdcd9 100644
--- a/of/ctl/pom.xml
+++ b/of/ctl/pom.xml
@@ -38,6 +38,10 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.onlab.onos</groupId>
+            <artifactId>onos-of-api</artifactId>
+        </dependency>
         <!-- ONOS's direct dependencies -->
         <dependency>
             <groupId>org.apache.felix</groupId>
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/IOFSwitch.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/IOFSwitch.java
deleted file mode 100644
index afa3703..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/IOFSwitch.java
+++ /dev/null
@@ -1,584 +0,0 @@
-/**
- *    Copyright 2011, Big Switch Networks, Inc.
- *    Originally created by David Erickson, Stanford University
- *
- *    Licensed under the Apache License, Version 2.0 (the "License"); you may
- *    not use this file except in compliance with the License. You may obtain
- *    a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *    License for the specific language governing permissions and limitations
- *    under the License.
- **/
-
-package org.onlab.onos.of.controller.impl;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Future;
-
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService.CounterException;
-import org.onlab.onos.of.controller.impl.util.OrderedCollection;
-
-import org.jboss.netty.channel.Channel;
-import org.projectfloodlight.openflow.protocol.OFActionType;
-import org.projectfloodlight.openflow.protocol.OFCapabilities;
-import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
-import org.projectfloodlight.openflow.protocol.OFMessage;
-import org.projectfloodlight.openflow.protocol.OFPortDesc;
-import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFPortStatus;
-import org.projectfloodlight.openflow.protocol.OFStatsReply;
-import org.projectfloodlight.openflow.protocol.OFStatsRequest;
-import org.projectfloodlight.openflow.protocol.OFVersion;
-import org.projectfloodlight.openflow.types.U64;
-
-
-public interface IOFSwitch {
-
-    /**
-     * OF1.3 switches should support role-request messages as in the 1.3 spec.
-     * OF1.0 switches may or may not support the Nicira role request extensions.
-     * To indicate the support, this property should be set by the associated
-     * OF1.0 switch driver in the net.onrc.onos.core.drivermanager package.
-     * The property will be ignored for OF1.3 switches.
-     */
-    public static final String SWITCH_SUPPORTS_NX_ROLE = "supportsNxRole";
-
-
-    //************************
-    // Channel related
-    //************************
-
-    /**
-     * Disconnects the switch by closing the TCP connection. Results in a call
-     * to the channel handler's channelDisconnected method for cleanup
-     * @throws IOException
-     */
-    public void disconnectSwitch();
-
-    /**
-     * Writes to the OFMessage to the output stream.
-     *
-     * @param m
-     * @throws IOException
-     */
-    public void write(OFMessage m) throws IOException;
-
-    /**
-     * Writes the list of messages to the output stream.
-     *
-     * @param msglist
-     * @throws IOException
-     */
-    public void write(List<OFMessage> msglist) throws IOException;
-
-    /**
-     * Gets the date the switch connected to this controller.
-     *
-     * @return the date
-     */
-    public Date getConnectedSince();
-
-    /**
-     * Gets the next available transaction id.
-     *
-     * @return the next transaction ID
-     */
-    public int getNextTransactionId();
-
-    /**
-     * Checks if the switch is still connected.
-     * Only call while holding processMessageLock
-     *
-     * @return whether the switch is still disconnected
-     */
-    public boolean isConnected();
-
-    /**
-     * Sets whether the switch is connected.
-     * Only call while holding modifySwitchLock
-     *
-     * @param connected whether the switch is connected
-     */
-    public void setConnected(boolean connected);
-
-    /**
-     * Flushes all flows queued for this switch in the current thread.
-     * NOTE: The contract is limited to the current thread
-     */
-    public void flush();
-
-    /**
-     * Sets the Netty Channel this switch instance is associated with.
-     * <p>
-     * Called immediately after instantiation
-     *
-     * @param channel the channel
-     */
-    public void setChannel(Channel channel);
-
-    //************************
-    // Switch features related
-    //************************
-
-    /**
-     * Gets the datapathId of the switch.
-     *
-     * @return the switch buffers
-     */
-    public long getId();
-
-    /**
-     * Gets a string version of the ID for this switch.
-     *
-     * @return string version of the ID
-     */
-    public String getStringId();
-
-    /**
-     * Gets the number of buffers.
-     *
-     * @return the number of buffers
-     */
-    public int getNumBuffers();
-
-    public Set<OFCapabilities> getCapabilities();
-
-    public byte getNumTables();
-
-    /**
-     * Returns an OFDescStatsReply message object. Use the methods contained
-     * to retrieve switch descriptions for Manufacturer, Hw/Sw version etc.
-     */
-    public OFDescStatsReply getSwitchDescription();
-
-    /**
-     * Cancel features reply with a specific transaction ID.
-     * @param transactionId the transaction ID
-     */
-    public void cancelFeaturesReply(int transactionId);
-
-    /**
-     * Gets the OFActionType set.
-     * <p>
-     * getActions has relevance only for an OpenFlow 1.0 switch.
-     * For OF1.3, each table can support different actions
-     *
-     * @return the action set
-     */
-    public Set<OFActionType> getActions();
-
-    public void setOFVersion(OFVersion ofv);
-
-    public OFVersion getOFVersion();
-
-
-    //************************
-    //  Switch port related
-    //************************
-
-    /**
-     * the type of change that happened to an open flow port.
-     */
-    public enum PortChangeType {
-        /** Either a new port has been added by the switch, or we are
-         * adding a port we just deleted (via a prior notification) due to
-         * a change in the portNumber-portName mapping.
-         */
-        ADD,
-        /** some other feature of the port has changed (eg. speed)*/
-        OTHER_UPDATE,
-        /** Either a port has been deleted by the switch, or we are deleting
-         * a port whose portNumber-portName mapping has changed. Note that in
-         * the latter case, a subsequent notification will be sent out to add a
-         * port with the new portNumber-portName mapping.
-         */
-        DELETE,
-        /** Port is up (i.e. enabled). Presumably an earlier notification had
-         * indicated that it was down. To be UP implies that the port is
-         * administratively considered UP (see ofp_port_config) AND the port
-         * link is up AND the port is no longer blocked (see ofp_port_state).
-         */
-        UP,
-        /** Port is down (i.e. disabled). Presumably an earlier notification had
-         * indicated that it was up, or the port was always up.
-         * To be DOWN implies that the port has been either
-         * administratively brought down (see ofp_port_config) OR the port
-         * link is down OR the port is blocked (see ofp_port_state).
-         */
-        DOWN,
-    }
-
-    /**
-     * Describes a change of an open flow port.
-     */
-    public static class PortChangeEvent {
-        public final OFPortDesc port;
-        public final PortChangeType type;
-        /**
-         * @param port
-         * @param type
-         */
-        public PortChangeEvent(OFPortDesc port,
-                               PortChangeType type) {
-            this.port = port;
-            this.type = type;
-        }
-        /* (non-Javadoc)
-         * @see java.lang.Object#hashCode()
-         */
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((port == null) ? 0 : port.hashCode());
-            result = prime * result + ((type == null) ? 0 : type.hashCode());
-            return result;
-        }
-        /* (non-Javadoc)
-         * @see java.lang.Object#equals(java.lang.Object)
-         */
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            PortChangeEvent other = (PortChangeEvent) obj;
-            if (port == null) {
-                if (other.port != null) {
-                    return false;
-                }
-            } else if (!port.equals(other.port)) {
-                return false;
-            }
-            if (type != other.type) {
-                return false;
-            }
-            return true;
-        }
-        /* (non-Javadoc)
-         * @see java.lang.Object#toString()
-         */
-        @Override
-        public String toString() {
-            return "[" + type + " " + port.toString() + "]";
-        }
-    }
-
-
-    /**
-     * Get list of all enabled ports. This will typically be different from
-     * the list of ports in the OFFeaturesReply, since that one is a static
-     * snapshot of the ports at the time the switch connected to the controller
-     * whereas this port list also reflects the port status messages that have
-     * been received.
-     *
-     * @return Unmodifiable list of ports not backed by the underlying collection
-     */
-    public Collection<OFPortDesc> getEnabledPorts();
-
-    /**
-     * Get list of the port numbers of all enabled ports. This will typically
-     * be different from the list of ports in the OFFeaturesReply, since that
-     * one is a static snapshot of the ports at the time the switch connected
-     * to the controller whereas this port list also reflects the port status
-     * messages that have been received.
-     *
-     * @return Unmodifiable list of ports not backed by the underlying collection
-     */
-    public Collection<Integer> getEnabledPortNumbers();
-
-    /**
-     * Retrieve the port object by the port number. The port object
-     * is the one that reflects the port status updates that have been
-     * received, not the one from the features reply.
-     *
-     * @param portNumber
-     * @return port object
-     */
-    public OFPortDesc getPort(int portNumber);
-
-    /**
-     * Retrieve the port object by the port name. The port object
-     * is the one that reflects the port status updates that have been
-     * received, not the one from the features reply.
-     *
-     * @param portName
-     * @return port object
-     */
-    public OFPortDesc getPort(String portName);
-
-    /**
-     * Add or modify a switch port. This is called by the core controller
-     * code in response to a OFPortStatus message.
-     *
-     * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow
-     * spec is not clear on whether portNames are portNumbers are considered
-     * authoritative identifiers. We treat portNames <-> portNumber mappings
-     * as fixed. If they change, we delete all previous conflicting ports and
-     * add all new ports.
-     *
-     * @param ps the port status message
-     * @return the ordered Collection of changes "applied" to the old ports
-     * of the switch according to the PortStatus message. A single PortStatus
-     * message can result in multiple changes.
-     * If portName <-> portNumber mappings have
-     * changed, the iteration order ensures that delete events for old
-     * conflicting appear before before events adding new ports
-     */
-    public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps);
-
-    /**
-     * Get list of all ports. This will typically be different from
-     * the list of ports in the OFFeaturesReply, since that one is a static
-     * snapshot of the ports at the time the switch connected to the controller
-     * whereas this port list also reflects the port status messages that have
-     * been received.
-     *
-     * @return Unmodifiable list of ports
-     */
-    public Collection<OFPortDesc> getPorts();
-
-    /**
-     * @param portName
-     * @return Whether a port is enabled per latest port status message
-     * (not configured down nor link down nor in spanning tree blocking state)
-     */
-    public boolean portEnabled(int portName);
-
-    /**
-     * @param portName
-     * @return Whether a port is enabled per latest port status message
-     * (not configured down nor link down nor in spanning tree blocking state)
-     */
-    public boolean portEnabled(String portName);
-
-    /**
-     * Compute the changes that would be required to replace the old ports
-     * of this switch with the new ports.
-     * @param ports new ports to set
-     * @return the ordered collection of changes "applied" to the old ports
-     * of the switch in order to set them to the new set.
-     * If portName <-> portNumber mappings have
-     * changed, the iteration order ensures that delete events for old
-     * conflicting appear before before events adding new ports
-     */
-    public OrderedCollection<PortChangeEvent>
-            comparePorts(Collection<OFPortDesc> ports);
-
-    /**
-     * Replace the ports of this switch with the given ports.
-     * @param ports new ports to set
-     * @return the ordered collection of changes "applied" to the old ports
-     * of the switch in order to set them to the new set.
-     * If portName <-> portNumber mappings have
-     * changed, the iteration order ensures that delete events for old
-     * conflicting appear before before events adding new ports
-     */
-    public OrderedCollection<PortChangeEvent>
-            setPorts(Collection<OFPortDesc> ports);
-
-    //*******************************************
-    //  IOFSwitch object attributes
-    //************************
-
-    /**
-     * Gets attributes of this switch.
-     *
-     * @return attributes of the switch
-     */
-    public Map<Object, Object> getAttributes();
-
-    /**
-     * Checks if a specific switch property exists for this switch.
-     *
-     * @param name name of property
-     * @return value for name
-     */
-    boolean hasAttribute(String name);
-
-    /**
-     * Gets properties for switch specific behavior.
-     *
-     * @param name name of property
-     * @return 'value' for 'name', or null if no entry for 'name' exists
-     */
-    Object getAttribute(String name);
-
-    /**
-     * Sets properties for switch specific behavior.
-     *
-     * @param name  name of property
-     * @param value value for name
-     */
-    void setAttribute(String name, Object value);
-
-    /**
-     * Removes properties for switch specific behavior.
-     *
-     * @param name name of property
-     * @return current value for name or null (if not present)
-     */
-    Object removeAttribute(String name);
-
-    //************************
-    //  Switch statistics
-    //************************
-
-    /**
-     * Delivers the statistics future reply.
-     *
-     * @param reply the reply to deliver
-     */
-    public void deliverStatisticsReply(OFMessage reply);
-
-    /**
-     * Cancels the statistics reply with the given transaction ID.
-     *
-     * @param transactionId the transaction ID
-     */
-    public void cancelStatisticsReply(int transactionId);
-
-    /**
-     * Cancels all statistics replies.
-     */
-    public void cancelAllStatisticsReplies();
-
-    /**
-     * Gets a Future object that can be used to retrieve the asynchronous.
-     * OFStatisticsReply when it is available.
-     *
-     * @param request statistics request
-     * @return Future object wrapping OFStatisticsReply
-     * @throws IOException
-     */
-    public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
-            throws IOException;
-
-    //************************
-    //  Switch other utilities
-    //************************
-
-    /**
-     * Clears all flowmods on this switch.
-     */
-    public void clearAllFlowMods();
-
-    /**
-     * Gets the current role of this controller for this IOFSwitch.
-     */
-    public Role getRole();
-
-    /**
-     * Sets this controller's Role for this IOFSwitch to role.
-     *
-     * @param role
-     */
-    public void setRole(Role role);
-
-    /**
-     * Gets the next generation ID.
-     * <p>
-     * Note: relevant for role request messages in OF1.3
-     *
-     * @return next generation ID
-     */
-    public U64 getNextGenerationId();
-
-
-    /**
-     * Set debug counter service for per-switch counters.
-     * Called immediately after instantiation.
-     * @param debugCounter
-     * @throws CounterException
-     */
-    public void setDebugCounterService(IDebugCounterService debugCounter)
-            throws CounterException;
-
-    /**
-     * Start this switch driver's sub handshake. This might be a no-op but
-     * this method must be called at least once for the switch to be become
-     * ready.
-     * This method must only be called from the I/O thread
-     * @throws IOException
-     * @throws org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeAlreadyStarted
-     * if the sub-handshake has
-     * already been started
-     */
-    public void startDriverHandshake() throws IOException;
-
-    /**
-     * Check if the sub-handshake for this switch driver has been completed.
-     * This method can only be called after startDriverHandshake()
-     *
-     * This methods must only be called from the I/O thread
-     * @return true if the sub-handshake has been completed. False otherwise
-     * @throws org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted
-     * if startDriverHandshake() has
-     * not been called yet.
-     */
-    public boolean isDriverHandshakeComplete();
-
-    /**
-     * Pass the given OFMessage to the driver as part of this driver's
-     * sub-handshake. Must not be called after the handshake has been completed
-     * This methods must only be called from the I/O thread
-     * @param m The message that the driver should process
-     * @throws org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeCompleted
-     * if isDriverHandshake() returns
-     * false before this method call
-     * @throws org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted
-     * if startDriverHandshake() has
-     * not been called yet.
-     */
-    public void processDriverHandshakeMessage(OFMessage m);
-
-    /**
-     * Set the flow table full flag in the switch.
-     * XXX S Rethink this for multiple tables
-     */
-    public void setTableFull(boolean isFull);
-
-    /**
-     * Save the features reply for this switch.
-     *
-     * @param featuresReply
-     */
-    public void setFeaturesReply(OFFeaturesReply featuresReply);
-
-    /**
-     * Save the portset for this switch.
-     *
-     * @param portDescReply
-     */
-    public void setPortDescReply(OFPortDescStatsReply portDescReply);
-
-    //************************
-    //  Message handling
-    //************************
-    /**
-     * Handle the message coming from the dataplane.
-     *
-     * @param m the actual message
-     */
-    public void handleMessage(OFMessage m);
-
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/Role.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/Role.java
deleted file mode 100644
index 081ea10..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/Role.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.onlab.onos.of.controller.impl;
-
-import org.projectfloodlight.openflow.protocol.OFControllerRole;
-
-/**
- * The role of the controller as it pertains to a particular switch.
- * Note that this definition of the role enum is different from the
- * OF1.3 definition. It is maintained here to be backward compatible to
- * earlier versions of the controller code. This enum is translated
- * to the OF1.3 enum, before role messages are sent to the switch.
- * See sendRoleRequestMessage method in OFSwitchImpl
- */
-public enum Role {
-    EQUAL(OFControllerRole.ROLE_EQUAL),
-    MASTER(OFControllerRole.ROLE_MASTER),
-    SLAVE(OFControllerRole.ROLE_SLAVE);
-
-    private Role(OFControllerRole nxRole) {
-        nxRole.ordinal();
-    }
-    /*
-    private static Map<Integer,Role> nxRoleToEnum
-            = new HashMap<Integer,Role>();
-    static {
-        for(Role r: Role.values())
-            nxRoleToEnum.put(r.toNxRole(), r);
-    }
-    public int toNxRole() {
-        return nxRole;
-    }
-    // Return the enum representing the given nxRole or null if no
-    // such role exists
-    public static Role fromNxRole(int nxRole) {
-        return nxRoleToEnum.get(nxRole);
-    }*/
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/DebugCounter.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/DebugCounter.java
deleted file mode 100644
index f88a43e..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/DebugCounter.java
+++ /dev/null
@@ -1,727 +0,0 @@
-package org.onlab.onos.of.controller.impl.debugcounter;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-import com.google.common.collect.Sets;
-
-
-
-/**
- * This class implements a central store for all counters used for debugging the
- * system. For counters based on traffic-type, see ICounterStoreService.
- *
- */
-//CHECKSTYLE:OFF
-public class DebugCounter implements IDebugCounterService {
-    protected static final Logger log = LoggerFactory.getLogger(DebugCounter.class);
-
-    /**
-     * registered counters need a counter id.
-     */
-    protected AtomicInteger counterIdCounter = new AtomicInteger();
-
-    /**
-     * The counter value.
-     */
-    protected static class MutableLong {
-        long value = 0;
-        public void increment() { value += 1; }
-        public void increment(long incr) { value += incr; }
-        public long get() { return value; }
-        public void set(long val) { value = val; }
-      }
-
-    /**
-     * protected class to store counter information.
-     */
-    public static class CounterInfo {
-        String moduleCounterHierarchy;
-        String counterDesc;
-        CounterType ctype;
-        String moduleName;
-        String counterHierarchy;
-        int counterId;
-        boolean enabled;
-        String[] metaData;
-
-        public CounterInfo(int counterId, boolean enabled,
-                           String moduleName, String counterHierarchy,
-                           String desc, CounterType ctype, String... metaData) {
-            this.moduleCounterHierarchy = moduleName + "/" + counterHierarchy;
-            this.moduleName = moduleName;
-            this.counterHierarchy = counterHierarchy;
-            this.counterDesc = desc;
-            this.ctype = ctype;
-            this.counterId = counterId;
-            this.enabled = enabled;
-            this.metaData = metaData;
-        }
-
-        public String getModuleCounterHierarchy() { return moduleCounterHierarchy; }
-        public String getCounterDesc() { return counterDesc; }
-        public CounterType getCtype() { return ctype; }
-        public String getModuleName() { return moduleName; }
-        public String getCounterHierarchy() { return counterHierarchy; }
-        public int getCounterId() { return counterId; }
-        public boolean isEnabled() { return enabled; }
-        public String[] getMetaData() { return this.metaData.clone(); }
-    }
-
-    //******************
-    //   Global stores
-    //******************
-
-    /**
-     * Counter info for a debug counter.
-     */
-    public static class DebugCounterInfo {
-        CounterInfo cinfo;
-        AtomicLong cvalue;
-
-        public DebugCounterInfo(CounterInfo cinfo) {
-            this.cinfo = cinfo;
-            this.cvalue = new AtomicLong();
-        }
-        public CounterInfo getCounterInfo() {
-            return cinfo;
-        }
-        public Long getCounterValue() {
-            return cvalue.get();
-        }
-    }
-
-    /**
-     * Global debug-counter storage across all threads. These are
-     * updated from the local per thread counters by the flush counters method.
-     */
-    private static final DebugCounterInfo[] ALLCOUNTERS =
-                            new DebugCounterInfo[MAX_COUNTERS];
-
-
-    /**
-     * per module counters, indexed by the module name and storing three levels
-     * of Counter information in the form of CounterIndexStore.
-     */
-    protected ConcurrentHashMap<String, ConcurrentHashMap<String, CounterIndexStore>>
-        moduleCounters = new ConcurrentHashMap<String,
-                                                ConcurrentHashMap<String,
-                                                                   CounterIndexStore>>();
-
-    protected static class CounterIndexStore {
-        int index;
-        Map<String, CounterIndexStore> nextLevel;
-
-        public CounterIndexStore(int index, Map<String, CounterIndexStore> cis) {
-            this.index = index;
-            this.nextLevel = cis;
-        }
-    }
-
-    /**
-     * fast global cache for counter ids that are currently active.
-     */
-    protected Set<Integer> currentCounters = Collections.newSetFromMap(
-                                         new ConcurrentHashMap<Integer, Boolean>());
-
-    //******************
-    // Thread local stores
-    //******************
-
-    /**
-     * Thread local storage of counter info.
-     */
-    protected static class LocalCounterInfo {
-        boolean enabled;
-        MutableLong cvalue;
-
-        public LocalCounterInfo(boolean enabled) {
-            this.enabled = enabled;
-            this.cvalue = new MutableLong();
-        }
-    }
-
-    /**
-     * Thread local debug counters used for maintaining counters local to a thread.
-     */
-    protected final ThreadLocal<LocalCounterInfo[]> threadlocalCounters =
-            new ThreadLocal<LocalCounterInfo[]>() {
-        @Override
-        protected LocalCounterInfo[] initialValue() {
-            return new LocalCounterInfo[MAX_COUNTERS];
-        }
-    };
-
-    /**
-     * Thread local cache for counter ids that are currently active.
-     */
-    protected final ThreadLocal<Set<Integer>> threadlocalCurrentCounters =
-            new ThreadLocal<Set<Integer>>() {
-        @Override
-        protected Set<Integer> initialValue() {
-            return new HashSet<Integer>();
-        }
-    };
-
-    //*******************************
-    //   IDebugCounter
-    //*******************************
-
-    protected class CounterImpl implements IDebugCounter {
-        private final int counterId;
-
-        public CounterImpl(int counterId) {
-            this.counterId = counterId;
-        }
-
-        @Override
-        public void updateCounterWithFlush() {
-            if (!validCounterId()) {
-                return;
-            }
-            updateCounter(counterId, 1, true);
-        }
-
-        @Override
-        public void updateCounterNoFlush() {
-            if (!validCounterId()) {
-                return;
-            }
-            updateCounter(counterId, 1, false);
-        }
-
-        @Override
-        public void updateCounterWithFlush(int incr) {
-            if (!validCounterId()) {
-                return;
-            }
-            updateCounter(counterId, incr, true);
-        }
-
-        @Override
-        public void updateCounterNoFlush(int incr) {
-            if (!validCounterId()) {
-                return;
-            }
-            updateCounter(counterId, incr, false);
-        }
-
-        @Override
-        public long getCounterValue() {
-            if (!validCounterId()) {
-                return -1;
-            }
-            return ALLCOUNTERS[counterId].cvalue.get();
-        }
-
-        /**
-         * Checks if this is a valid counter.
-         * @return true if the counter id is valid
-         */
-        private boolean validCounterId() {
-            if (counterId < 0 || counterId >= MAX_COUNTERS) {
-                log.error("Invalid counterId invoked");
-                return false;
-            }
-            return true;
-        }
-
-    }
-
-   //*******************************
-   //   IDebugCounterService
-   //*******************************
-
-   @Override
-   public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
-                           String counterDescription, CounterType counterType,
-                           String... metaData)
-               throws CounterException {
-       // check if counter already exists
-       if (!moduleCounters.containsKey(moduleName)) {
-           moduleCounters.putIfAbsent(moduleName,
-                new ConcurrentHashMap<String, CounterIndexStore>());
-       }
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (rci.allLevelsFound) {
-           // counter exists
-           log.info("Counter exists for {}/{} -- resetting counters", moduleName,
-                    counterHierarchy);
-           resetCounterHierarchy(moduleName, counterHierarchy);
-           return new CounterImpl(rci.ctrIds[rci.foundUptoLevel - 1]);
-       }
-       // check for validity of counter
-       if (rci.levels.length > MAX_HIERARCHY) {
-           String err = "Registry of counterHierarchy " + counterHierarchy +
-                   " exceeds max hierachy " + MAX_HIERARCHY + ".. aborting";
-           throw new MaxHierarchyRegistered(err);
-       }
-       if (rci.foundUptoLevel < rci.levels.length - 1) {
-           StringBuilder sb = new StringBuilder();
-           for (int i = 0; i <= rci.foundUptoLevel; i++) {
-               sb.append(rci.levels[i]);
-           }
-           String needToRegister = sb.toString();
-           String err = "Attempting to register hierarchical counterHierarchy " +
-                   counterHierarchy + " but parts of hierarchy missing. " +
-                   "Please register " +  needToRegister + " first";
-           throw new MissingHierarchicalLevel(err);
-       }
-
-       // get a new counter id
-       int counterId = counterIdCounter.getAndIncrement();
-       if (counterId >= MAX_COUNTERS) {
-           throw new MaxCountersRegistered("max counters reached");
-       }
-       // create storage for counter
-       boolean enabled = (counterType == CounterType.ALWAYS_COUNT) ? true : false;
-       CounterInfo ci = new CounterInfo(counterId, enabled, moduleName,
-                                        counterHierarchy, counterDescription,
-                                        counterType, metaData);
-       ALLCOUNTERS[counterId] = new DebugCounterInfo(ci);
-
-       // account for the new counter in the module counter hierarchy
-       addToModuleCounterHierarchy(moduleName, counterId, rci);
-
-       // finally add to active counters
-       if (enabled) {
-           currentCounters.add(counterId);
-       }
-       return new CounterImpl(counterId);
-   }
-
-   private void updateCounter(int counterId, int incr, boolean flushNow) {
-       if (counterId < 0 || counterId >= MAX_COUNTERS) {
-        return;
-    }
-
-       LocalCounterInfo[] thiscounters =  this.threadlocalCounters.get();
-       if (thiscounters[counterId] == null) {
-           // seeing this counter for the first time in this thread - create local
-           // store by consulting global store
-           DebugCounterInfo dc = ALLCOUNTERS[counterId];
-           if (dc != null) {
-               thiscounters[counterId] = new LocalCounterInfo(dc.cinfo.enabled);
-               if (dc.cinfo.enabled) {
-                   Set<Integer> thisset = this.threadlocalCurrentCounters.get();
-                   thisset.add(counterId);
-               }
-           } else {
-               log.error("updateCounter seen locally for counter {} but no global"
-                          + "storage exists for it yet .. not updating", counterId);
-               return;
-           }
-       }
-
-       // update local store if enabled locally for updating
-       LocalCounterInfo lc = thiscounters[counterId];
-       if (lc.enabled) {
-           lc.cvalue.increment(incr);
-           if (flushNow) {
-               DebugCounterInfo dc = ALLCOUNTERS[counterId];
-               if (dc.cinfo.enabled) {
-                   // globally enabled - flush now
-                   dc.cvalue.addAndGet(lc.cvalue.get());
-                   lc.cvalue.set(0);
-               } else {
-                   // global counter is disabled - don't flush, disable locally
-                   lc.enabled = false;
-                   Set<Integer> thisset = this.threadlocalCurrentCounters.get();
-                   thisset.remove(counterId);
-               }
-           }
-       }
-   }
-
-   @Override
-   public void flushCounters() {
-       LocalCounterInfo[] thiscounters =  this.threadlocalCounters.get();
-       Set<Integer> thisset = this.threadlocalCurrentCounters.get();
-       ArrayList<Integer> temp = new ArrayList<Integer>();
-
-       for (int counterId : thisset) {
-           LocalCounterInfo lc = thiscounters[counterId];
-           if (lc.cvalue.get() > 0) {
-               DebugCounterInfo dc = ALLCOUNTERS[counterId];
-               if (dc.cinfo.enabled) {
-                   // globally enabled - flush now
-                   dc.cvalue.addAndGet(lc.cvalue.get());
-                   lc.cvalue.set(0);
-               } else {
-                   // global counter is disabled - don't flush, disable locally
-                   lc.enabled = false;
-                   temp.add(counterId);
-               }
-           }
-       }
-       for (int cId : temp) {
-           thisset.remove(cId);
-       }
-
-       // At this point it is possible that the thread-local set does not
-       // include a counter that has been enabled and is present in the global set.
-       // We need to sync thread-local currently enabled set of counterIds with
-       // the global set.
-       Sets.SetView<Integer> sv = Sets.difference(currentCounters, thisset);
-       for (int counterId : sv) {
-           if (thiscounters[counterId] != null) {
-               thiscounters[counterId].enabled = true;
-               thisset.add(counterId);
-           }
-       }
-   }
-
-   @Override
-   public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot reset counter hierarchy - missing counter {}", missing);
-           return;
-       }
-       // reset at this level
-       ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]].cvalue.set(0);
-       // reset all levels below
-       ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-       for (int index : resetIds) {
-           ALLCOUNTERS[index].cvalue.set(0);
-       }
-   }
-
-   @Override
-   public void resetAllCounters() {
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-       for (String moduleName : moduleCounters.keySet()) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               ALLCOUNTERS[index].cvalue.set(0);
-           }
-       }
-   }
-
-   @Override
-   public void resetAllModuleCounters(String moduleName) {
-       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       if (target != null) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               ALLCOUNTERS[index].cvalue.set(0);
-           }
-       } else {
-           if (log.isDebugEnabled()) {
-            log.debug("No module found with name {}", moduleName);
-        }
-       }
-   }
-
-   @Override
-   public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot enable counter - counter not found {}", missing);
-           return;
-       }
-       // enable specific counter
-       DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
-       dc.cinfo.enabled = true;
-       currentCounters.add(dc.cinfo.counterId);
-   }
-
-   @Override
-   public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot disable counter - counter not found {}", missing);
-           return;
-       }
-       // disable specific counter
-       DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
-       if (dc.cinfo.ctype == CounterType.COUNT_ON_DEMAND) {
-           dc.cinfo.enabled = false;
-           dc.cvalue.set(0);
-           currentCounters.remove(dc.cinfo.counterId);
-       }
-   }
-
-   @Override
-   public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
-                                                     String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot fetch counter - counter not found {}", missing);
-           return Collections.emptyList();
-       }
-       ArrayList<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
-       // get counter and all below it
-       DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
-       dcilist.add(dc);
-       ArrayList<Integer> belowIds = getHierarchyBelow(moduleName, rci);
-       for (int index : belowIds) {
-           dcilist.add(ALLCOUNTERS[index]);
-       }
-       return dcilist;
-   }
-
-   @Override
-   public List<DebugCounterInfo> getAllCounterValues() {
-       List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       for (String moduleName : moduleCounters.keySet()) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               dcilist.add(ALLCOUNTERS[index]);
-           }
-       }
-       return dcilist;
-   }
-
-   @Override
-   public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
-       List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       if (moduleCounters.containsKey(moduleName)) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               dcilist.add(ALLCOUNTERS[index]);
-           }
-       }
-       return dcilist;
-   }
-
-   @Override
-   public boolean containsModuleCounterHierarchy(String moduleName,
-                                                 String counterHierarchy) {
-       if (!moduleCounters.containsKey(moduleName)) {
-        return false;
-    }
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       return rci.allLevelsFound;
-   }
-
-   @Override
-   public boolean containsModuleName(String moduleName) {
-       return  (moduleCounters.containsKey(moduleName)) ? true : false;
-   }
-
-   @Override
-   public List<String> getModuleList() {
-       List<String> retval = new ArrayList<String>();
-       retval.addAll(moduleCounters.keySet());
-       return retval;
-   }
-
-   @Override
-   public List<String> getModuleCounterList(String moduleName) {
-       if (!moduleCounters.containsKey(moduleName)) {
-        return Collections.emptyList();
-    }
-
-       List<String> retval = new ArrayList<String>();
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       ArrayList<Integer> cids = getHierarchyBelow(moduleName, rci);
-       for (int index : cids) {
-           retval.add(ALLCOUNTERS[index].cinfo.counterHierarchy);
-       }
-       return retval;
-   }
-
-   //*******************************
-   //   Internal Methods
-   //*******************************
-
-   protected class RetCtrInfo {
-       boolean allLevelsFound; // counter indices found all the way down the hierarchy
-       boolean hierarchical; // true if counterHierarchy is hierarchical
-       int foundUptoLevel;
-       int[]  ctrIds;
-       String[] levels;
-
-       public RetCtrInfo() {
-           ctrIds = new int[MAX_HIERARCHY];
-           for (int i = 0; i < MAX_HIERARCHY; i++) {
-               ctrIds[i] = -1;
-           }
-       }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + getOuterType().hashCode();
-        result = prime * result + (allLevelsFound ? 1231 : 1237);
-        result = prime * result + Arrays.hashCode(ctrIds);
-        result = prime * result + foundUptoLevel;
-        result = prime * result + (hierarchical ? 1231 : 1237);
-        result = prime * result + Arrays.hashCode(levels);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object oth) {
-        if (!(oth instanceof RetCtrInfo)) {
-         return false;
-     }
-        RetCtrInfo other = (RetCtrInfo) oth;
-        if (other.allLevelsFound != this.allLevelsFound) {
-         return false;
-     }
-        if (other.hierarchical != this.hierarchical) {
-         return false;
-     }
-        if (other.foundUptoLevel != this.foundUptoLevel) {
-         return false;
-     }
-        if (!Arrays.equals(other.ctrIds, this.ctrIds)) {
-         return false;
-     }
-        if (!Arrays.equals(other.levels, this.levels)) {
-         return false;
-     }
-        return true;
-    }
-
-    private DebugCounter getOuterType() {
-        return DebugCounter.this;
-    }
-
-
-
-   }
-
-   protected RetCtrInfo getCounterId(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = new RetCtrInfo();
-       Map<String, CounterIndexStore> templevel = moduleCounters.get(moduleName);
-       rci.levels = counterHierarchy.split("/");
-       if (rci.levels.length > 1) {
-        rci.hierarchical = true;
-    }
-       if (templevel == null) {
-           log.error("moduleName {} does not exist in debugCounters", moduleName);
-           return rci;
-       }
-
-       /*
-       if (rci.levels.length > MAX_HIERARCHY) {
-           // chop off all array elems greater that MAX_HIERARCHY
-           String[] temp = new String[MAX_HIERARCHY];
-           System.arraycopy(rci.levels, 0, temp, 0, MAX_HIERARCHY);
-           rci.levels = temp;
-       }
-       */
-       for (int i = 0; i < rci.levels.length; i++) {
-           if (templevel != null) {
-               CounterIndexStore cis = templevel.get(rci.levels[i]);
-               if (cis == null) {
-                   // could not find counterHierarchy part at this level
-                   break;
-               } else {
-                   rci.ctrIds[i] = cis.index;
-                   templevel = cis.nextLevel;
-                   rci.foundUptoLevel++;
-                   if (i == rci.levels.length - 1) {
-                       rci.allLevelsFound = true;
-                   }
-               }
-           } else {
-               // there are no more levels, which means that some part of the
-               // counterHierarchy has no corresponding map
-               break;
-           }
-       }
-       return rci;
-   }
-
-   protected void addToModuleCounterHierarchy(String moduleName, int counterId,
-                                            RetCtrInfo rci) {
-       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
-       if (target == null) {
-        return;
-    }
-       CounterIndexStore cis = null;
-
-       for (int i = 0; i < rci.foundUptoLevel; i++) {
-           cis = target.get(rci.levels[i]);
-           target = cis.nextLevel;
-       }
-       if (cis != null) {
-           if (cis.nextLevel == null) {
-            cis.nextLevel = new ConcurrentHashMap<String, CounterIndexStore>();
-        }
-           cis.nextLevel.put(rci.levels[rci.foundUptoLevel],
-                             new CounterIndexStore(counterId, null));
-       } else {
-           target.put(rci.levels[rci.foundUptoLevel],
-                      new CounterIndexStore(counterId, null));
-       }
-   }
-
-   // given a partial hierarchical counter, return the rest of the hierarchy
-   protected ArrayList<Integer> getHierarchyBelow(String moduleName, RetCtrInfo rci) {
-       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
-       CounterIndexStore cis = null;
-       ArrayList<Integer> retval = new ArrayList<Integer>();
-       if (target == null) {
-        return retval;
-    }
-
-       // get to the level given
-       for (int i = 0; i < rci.foundUptoLevel; i++) {
-           cis = target.get(rci.levels[i]);
-           target = cis.nextLevel;
-       }
-
-       if (target == null || rci.foundUptoLevel == MAX_HIERARCHY) {
-           // no more levels
-           return retval;
-       } else {
-           // recursively get all ids
-           getIdsAtLevel(target, retval, rci.foundUptoLevel + 1);
-       }
-
-       return retval;
-   }
-
-   protected void getIdsAtLevel(Map<String, CounterIndexStore> hcy,
-                                ArrayList<Integer> retval, int level) {
-       if (level > MAX_HIERARCHY) {
-        return;
-    }
-       if (hcy == null || retval == null) {
-        return;
-    }
-
-       // Can return the counter names as well but for now ids are enough.
-       for (CounterIndexStore cistemp : hcy.values()) {
-           retval.add(cistemp.index); // value at this level
-           if (cistemp.nextLevel != null) {
-               getIdsAtLevel(cistemp.nextLevel, retval, level + 1);
-           }
-       }
-   }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/IDebugCounter.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/IDebugCounter.java
deleted file mode 100644
index 2dc0c0a..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/IDebugCounter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.onlab.onos.of.controller.impl.debugcounter;
-
-public interface IDebugCounter {
-    /**
-     * Increments the counter by 1 thread-locally, and immediately flushes to
-     * the global counter storage. This method should be used for counters that
-     * are updated outside the OF message processing pipeline.
-     */
-    void updateCounterWithFlush();
-
-    /**
-     * Increments the counter by 1 thread-locally. Flushing to the global
-     * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
-     * resulting in higher performance. This method should be used for counters
-     * updated in the OF message processing pipeline.
-     */
-    void updateCounterNoFlush();
-
-    /**
-     * Increments the counter thread-locally by the 'incr' specified, and immediately
-     * flushes to the global counter storage. This method should be used for counters
-     * that are updated outside the OF message processing pipeline.
-     */
-    void updateCounterWithFlush(int incr);
-
-    /**
-     * Increments the counter thread-locally by the 'incr' specified. Flushing to the global
-     * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
-     * resulting in higher performance. This method should be used for counters
-     * updated in the OF message processing pipeline.
-     */
-    void updateCounterNoFlush(int incr);
-
-    /**
-     * Retrieve the value of the counter from the global counter store.
-     */
-    long getCounterValue();
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/IDebugCounterService.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/IDebugCounterService.java
deleted file mode 100644
index 216ee74..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/IDebugCounterService.java
+++ /dev/null
@@ -1,262 +0,0 @@
-package org.onlab.onos.of.controller.impl.debugcounter;
-
-
-
-import java.util.List;
-
-import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter.DebugCounterInfo;
-
-//CHECKSTYLE:OFF
-public interface IDebugCounterService {
-
-    /**
-     * Different counter types. Counters that are meant to be counted-on-demand
-     * need to be separately enabled/disabled.
-     */
-    public enum CounterType {
-        ALWAYS_COUNT,
-        COUNT_ON_DEMAND
-    }
-
-    /**
-     * Debug Counter Qualifiers.
-     */
-    public static final String CTR_MDATA_WARN = "warn";
-    public static final String CTR_MDATA_ERROR = "error";
-    public static final String CTR_MDATA_DROP = "drop";
-
-    /**
-     *  A limit on the maximum number of counters that can be created.
-     */
-    public static final int MAX_COUNTERS = 5000;
-
-    /**
-     * Exception thrown when MAX_COUNTERS have been registered.
-     */
-    public class MaxCountersRegistered extends CounterException {
-        private static final long serialVersionUID = 3173747663719376745L;
-        String errormsg;
-        public MaxCountersRegistered(String errormsg) {
-            this.errormsg = errormsg;
-        }
-        @Override
-        public String getMessage() {
-            return this.errormsg;
-        }
-    }
-    /**
-     * Exception thrown when MAX_HIERARCHY has been reached.
-     */
-    public class MaxHierarchyRegistered extends CounterException {
-        private static final long serialVersionUID = 967431358683523871L;
-        private String errormsg;
-        public MaxHierarchyRegistered(String errormsg) {
-            this.errormsg = errormsg;
-        }
-        @Override
-        public String getMessage() {
-            return this.errormsg;
-        }
-    }
-    /**
-     * Exception thrown when attempting to register a hierarchical counter
-     * where higher levels of the hierarchy have not been pre-registered.
-     */
-    public class MissingHierarchicalLevel extends CounterException {
-        private static final long serialVersionUID = 517315311533995739L;
-        private String errormsg;
-        public MissingHierarchicalLevel(String errormsg) {
-            this.errormsg = errormsg;
-        }
-        @Override
-        public String getMessage() {
-            return this.errormsg;
-        }
-    }
-
-    public class CounterException extends Exception {
-        private static final long serialVersionUID = 2219781500857866035L;
-    }
-
-    /**
-     *  maximum levels of hierarchy.
-     *  Example of moduleName/counterHierarchy:
-     *           switch/00:00:00:00:01:02:03:04/pktin/drops where
-     *           moduleName ==> "switch"  and
-     *           counterHierarchy of 3 ==> "00:00:00:00:01:02:03:04/pktin/drops"
-     */
-    public static final int MAX_HIERARCHY = 3;
-
-    /**
-     * All modules that wish to have the DebugCounterService count for them, must
-     * register their counters by making this call (typically from that module's
-     * 'startUp' method). The counter can then be updated, displayed, reset etc.
-     * using the registered moduleName and counterHierarchy.
-     *
-     * @param moduleName           the name of the module which is registering the
-     *                             counter eg. linkdiscovery or controller or switch
-     * @param counterHierarchy     the hierarchical counter name specifying all
-     *                             the hierarchical levels that come above it.
-     *                             For example: to register a drop counter for
-     *                             packet-ins from a switch, the counterHierarchy
-     *                             can be "00:00:00:00:01:02:03:04/pktin/drops"
-     *                             It is necessary that counters in hierarchical levels
-     *                             above have already been pre-registered - in this
-     *                             example: "00:00:00:00:01:02:03:04/pktin" and
-     *                             "00:00:00:00:01:02:03:04"
-     * @param counterDescription   a descriptive string that gives more information
-     *                             of what the counter is measuring. For example,
-     *                             "Measures the number of incoming packets seen by
-     *                             this module".
-     * @param counterType          One of CounterType. On-demand counter types
-     *                             need to be explicitly enabled/disabled using other
-     *                             methods in this API -- i.e. registering them is
-     *                             not enough to start counting.
-     * @param metaData             variable arguments that qualify a counter
-     *                             eg. warn, error etc.
-     * @return                     IDebugCounter with update methods that can be
-     *                             used to update a counter.
-     * @throws MaxCountersRegistered
-     * @throws MaxHierarchyRegistered
-     * @throws MissingHierarchicalLevel
-     */
-    public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
-                             String counterDescription, CounterType counterType,
-                             String... metaData)
-                throws CounterException;
-
-    /**
-     * Flush all thread-local counter values (from the current thread)
-     * to the global counter store. This method is not intended for use by any
-     * module. It's typical usage is from core and it is meant
-     * to flush those counters that are updated in the packet-processing pipeline,
-     * typically with the 'updateCounterNoFlush" methods in IDebugCounter.
-     */
-    public void flushCounters();
-
-    /**
-     * Resets the value of counters in the hierarchy to zero. Note that the reset
-     * applies to the level of counter hierarchy specified AND ALL LEVELS BELOW it
-     * in the hierarchy.
-     * For example: If a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops"
-     *              specifying a reset hierarchy: "00:00:00:00:01:02:03:04"
-     *              will reset all counters for the switch dpid specified;
-     *              while specifying a reset hierarchy: ""00:00:00:00:01:02:03:04/pktin"
-     *              will reset the pktin counter and all levels below it (like drops)
-     *              for the switch dpid specified.
-     */
-    void resetCounterHierarchy(String moduleName, String counterHierarchy);
-
-    /**
-     * Resets the values of all counters in the system.
-     */
-    public void resetAllCounters();
-
-    /**
-     * Resets the values of all counters belonging
-     * to a module with the given 'moduleName'.
-     */
-    public void resetAllModuleCounters(String moduleName);
-
-    /**
-     * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
-     * enable counting on the counter. Note that this step is necessary to start
-     * counting for these counter types - merely registering the counter is not
-     * enough (as is the case for CounterType.ALWAYS_COUNT). Newly
-     * enabled counters start from an initial value of zero.
-     *
-     * Enabling a counter in a counterHierarchy enables only THAT counter. It
-     * does not enable any other part of the counterHierarchy. For example, if
-     * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
-     * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then enabling
-     * the 'pktin' counter by specifying the counterHierarchy as
-     * "00:00:00:00:01:02:03:04/pktin" does NOT enable the 'drops' counter.
-     */
-    public void enableCtrOnDemand(String moduleName, String counterHierarchy);
-
-    /**
-     * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
-     * enable counting on the counter. Note that disabling a counter results in a loss
-     * of the counter value. When re-enabled the counter will restart from zero.
-     *
-     * Disabling a counter in a counterHierarchy disables only THAT counter. It
-     * does not disable any other part of the counterHierarchy. For example, if
-     * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
-     * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then disabling
-     * the 'pktin' counter by specifying the counterHierarchy as
-     * "00:00:00:00:01:02:03:04/pktin" does NOT disable the 'drops' counter.
-     */
-    public void disableCtrOnDemand(String moduleName, String counterHierarchy);
-
-    /**
-     * Get counter value and associated information for the specified counterHierarchy.
-     * Note that information on the level of counter hierarchy specified
-     * AND ALL LEVELS BELOW it in the hierarchy will be returned.
-     *
-     * For example,
-     * if a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", then
-     * specifying a counterHierarchy of "00:00:00:00:01:02:03:04/pktin" in the
-     * get call will return information on the 'pktin' as well as the 'drops'
-     * counters for the switch dpid specified.
-     *
-     * @return A list of DebugCounterInfo or an empty list if the counter
-     *         could not be found
-     */
-    public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
-                                                      String counterHierarchy);
-
-    /**
-     * Get counter values and associated information for all counters in the
-     * system.
-     *
-     * @return the list of values/info or an empty list
-     */
-    public  List<DebugCounterInfo> getAllCounterValues();
-
-    /**
-     * Get counter values and associated information for all counters associated
-     * with a module.
-     *
-     * @param moduleName
-     * @return the list of values/info or an empty list
-     */
-    public  List<DebugCounterInfo> getModuleCounterValues(String moduleName);
-
-    /**
-     * Convenience method to figure out if the the given 'counterHierarchy' corresponds
-     * to a registered counterHierarchy for 'moduleName'. Note that the counter may or
-     * may not be enabled for counting, but if it is registered the method will
-     * return true.
-     *
-     * @param moduleName
-     * @param counterHierarchy
-     * @return false if moduleCounterHierarchy is not a registered counter
-     */
-    public boolean containsModuleCounterHierarchy(String moduleName,
-                                                  String counterHierarchy);
-
-    /**
-     * Convenience method to figure out if the the given 'moduleName' corresponds
-     * to a registered moduleName or not. Note that the module may or may not have
-     * a counter enabled for counting, but if it is registered the method will
-     * return true.
-     *
-     * @param moduleName
-     * @return false if moduleName is not a registered counter
-     */
-    public boolean containsModuleName(String moduleName);
-
-    /**
-     * Returns a list of moduleNames registered for debug counters or an empty
-     * list if no counters have been registered in the system.
-     */
-    public List<String> getModuleList();
-
-    /**
-     * Returns a list of all counters registered for a specific moduleName
-     * or a empty list.
-     */
-    public List<String> getModuleCounterList(String moduleName);
-
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/NullDebugCounter.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/NullDebugCounter.java
deleted file mode 100644
index ae476ea..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/debugcounter/NullDebugCounter.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.onlab.onos.of.controller.impl.debugcounter;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter.DebugCounterInfo;
-
-//CHECKSTYLE:OFF
-public class NullDebugCounter implements IDebugCounterService {
-
-    @Override
-    public void flushCounters() {
-
-    }
-
-    @Override
-    public void resetAllCounters() {
-
-    }
-
-    @Override
-    public void resetAllModuleCounters(String moduleName) {
-
-    }
-
-
-    @Override
-    public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
-
-    }
-
-    @Override
-    public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
-
-    }
-
-    @Override
-    public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
-
-    }
-
-    @Override
-    public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
-                                                      String counterHierarchy) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<DebugCounterInfo> getAllCounterValues() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public boolean containsModuleCounterHierarchy(String moduleName,
-                                             String counterHierarchy) {
-        return false;
-    }
-
-    @Override
-    public boolean containsModuleName(String moduleName) {
-        return false;
-    }
-
-    @Override
-    public
-            IDebugCounter
-            registerCounter(String moduleName, String counterHierarchy,
-                            String counterDescription,
-                            CounterType counterType, String... metaData)
-                                 throws MaxCountersRegistered {
-        return new NullCounterImpl();
-    }
-
-    @Override
-    public List<String> getModuleList() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<String> getModuleCounterList(String moduleName) {
-        return Collections.emptyList();
-    }
-
-    public static class NullCounterImpl implements IDebugCounter {
-
-        @Override
-        public void updateCounterWithFlush() {
-
-        }
-
-        @Override
-        public void updateCounterNoFlush() {
-
-        }
-
-        @Override
-        public void updateCounterWithFlush(int incr) {
-        }
-
-        @Override
-        public void updateCounterNoFlush(int incr) {
-
-        }
-
-        @Override
-        public long getCounterValue() {
-            return -1;
-        }
-
-    }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
new file mode 100644
index 0000000..7f4830d
--- /dev/null
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
@@ -0,0 +1,279 @@
+/**
+ *    Copyright 2011, Big Switch Networks, Inc.
+ *    Originally created by David Erickson, Stanford University
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
+package org.onlab.onos.of.controller.impl.internal;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.jboss.netty.channel.Channel;
+import org.onlab.onos.of.controller.Dpid;
+import org.onlab.onos.of.controller.OpenFlowSwitch;
+import org.onlab.onos.of.controller.RoleState;
+import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
+import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleRecvStatus;
+import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleReplyInfo;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFRoleReply;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
+
+    private static Logger log =
+            LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
+
+    private Channel channel;
+    private boolean connected;
+    private Dpid dpid;
+    private OpenFlowSwitchAgent agent;
+
+    private OFVersion ofVersion;
+
+    protected OFPortDescStatsReply ports;
+
+    protected boolean tableFull;
+
+    private final RoleManager roleMan = new RoleManager(this);
+
+    protected AbstractOpenFlowSwitch(long dpid) {
+        this.dpid = new Dpid(dpid);
+    }
+
+    //************************
+    // Channel related
+    //************************
+
+    /**
+     * Disconnects the switch by closing the TCP connection. Results in a call
+     * to the channel handler's channelDisconnected method for cleanup
+     * @throws IOException
+     */
+    public final void disconnectSwitch() {
+        this.channel.close();
+    }
+
+    /**
+     * Writes to the OFMessage to the output stream.
+     *
+     * @param m the message to be written
+     */
+    public abstract void write(OFMessage m);
+
+    /**
+     * Writes to the OFMessage list to the output stream.
+     *
+     * @param msgs the messages to be written
+     */
+    public abstract void write(List<OFMessage> msgs);
+
+
+    /**
+     * Checks if the switch is still connected.
+     * Only call while holding processMessageLock
+     *
+     * @return whether the switch is still disconnected
+     */
+    public final boolean isConnected() {
+        return this.connected;
+    }
+
+    /**
+     * Sets whether the switch is connected.
+     * Only call while holding modifySwitchLock
+     *
+     * @param connected whether the switch is connected
+     */
+    final void setConnected(boolean connected) {
+        this.connected = connected;
+    };
+
+    /**
+     * Sets the Netty Channel this switch instance is associated with.
+     * <p>
+     * Called immediately after instantiation
+     *
+     * @param channel the channel
+     */
+    public final void setChannel(Channel channel) {
+        this.channel = channel;
+    };
+
+    //************************
+    // Switch features related
+    //************************
+
+    /**
+     * Gets the datapathId of the switch.
+     *
+     * @return the switch buffers
+     */
+    public final long getId() {
+        return this.dpid.value();
+    };
+
+    /**
+     * Gets a string version of the ID for this switch.
+     *
+     * @return string version of the ID
+     */
+    public final String getStringId() {
+        return this.dpid.toString();
+    }
+
+    public final void setOFVersion(OFVersion ofV) {
+        this.ofVersion = ofV;
+    }
+
+    void setTableFull(boolean full) {
+        this.tableFull = full;
+    }
+
+    public abstract void setFeaturesReply(OFFeaturesReply featuresReply);
+
+    /**
+     * Let peoeple know if you support Nicira style role requests.
+     *
+     * @return support Nicira roles or not.
+     */
+    public abstract Boolean supportNxRole();
+
+    //************************
+    //  Message handling
+    //************************
+    /**
+     * Handle the message coming from the dataplane.
+     *
+     * @param m the actual message
+     */
+    public final void handleMessage(OFMessage m) {
+        this.agent.processMessage(m);
+    }
+
+    public abstract RoleState getRole();
+
+    final boolean addConnectedSwitch() {
+        return this.agent.addConnectedSwitch(this.getId(), this);
+    }
+
+    final boolean addActivatedMasterSwitch() {
+        return this.agent.addActivatedMasterSwitch(this.getId(), this);
+    }
+
+    final boolean addActivatedEqualSwitch() {
+        return this.agent.addActivatedEqualSwitch(this.getId(), this);
+    }
+
+    final void transitionToEqualSwitch() {
+        this.agent.transitionToEqualSwitch(this.getId());
+    }
+
+    final void transitionToMasterSwitch() {
+        this.agent.transitionToMasterSwitch(this.getId());
+    }
+
+    final void removeConnectedSwitch() {
+        this.agent.removeConnectedSwitch(this.getId());
+    }
+
+    protected OFFactory factory() {
+        return OFFactories.getFactory(ofVersion);
+    }
+
+    public void setPortDescReply(OFPortDescStatsReply portDescReply) {
+        this.ports = portDescReply;
+    }
+
+    public abstract void startDriverHandshake();
+
+    public abstract boolean isDriverHandshakeComplete();
+
+    public abstract void processDriverHandshakeMessage(OFMessage m);
+
+    public void setRole(RoleState role) {
+        try {
+            this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE);
+        } catch (IOException e) {
+           log.error("Unable to write to switch {}.", this.dpid);
+        }
+    }
+
+    // Role Handling
+
+    void handleRole(OFMessage m) throws SwitchStateException {
+        RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
+        RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
+        if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+            if (rri.getRole() == RoleState.MASTER) {
+                this.transitionToMasterSwitch();
+            } else if (rri.getRole() == RoleState.EQUAL ||
+                    rri.getRole() == RoleState.MASTER) {
+                this.transitionToEqualSwitch();
+            }
+        }
+    }
+
+    void handleNiciraRole(OFMessage m) throws SwitchStateException {
+        RoleState role = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
+      if (role == null) {
+          // The message wasn't really a Nicira role reply. We just
+          // dispatch it to the OFMessage listeners in this case.
+          this.handleMessage(m);
+      }
+
+      RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
+              new RoleReplyInfo(role, null, m.getXid()));
+          if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+              if (role == RoleState.MASTER) {
+                  this.transitionToMasterSwitch();
+              } else if (role == RoleState.EQUAL ||
+                      role == RoleState.SLAVE) {
+                  this.transitionToEqualSwitch();
+              }
+          }
+    }
+
+    boolean handleRoleError(OFErrorMsg error) {
+        try {
+            return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
+        } catch (SwitchStateException e) {
+            this.disconnectSwitch();
+        }
+        return true;
+    }
+
+    void reassertRole() {
+        if (this.getRole() == RoleState.MASTER) {
+            this.setRole(RoleState.MASTER);
+        }
+    }
+
+    void setAgent(OpenFlowSwitchAgent ag) {
+        this.agent = ag;
+    }
+
+
+
+}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
index 1f0b36d..6ae3abb 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/Controller.java
@@ -20,47 +20,22 @@
 import java.lang.management.ManagementFactory;
 import java.lang.management.RuntimeMXBean;
 import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executors;
 
-import org.onlab.onos.of.controller.impl.IOFSwitchManager;
-import org.onlab.onos.of.controller.impl.Role;
-import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
-import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
-import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounter;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService.CounterException;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService.CounterType;
-import org.onlab.onos.of.controller.impl.internal.OFChannelHandler.RoleRecvStatus;
-import org.onlab.onos.of.controller.impl.registry.IControllerRegistry;
-import org.onlab.onos.of.controller.impl.registry.RegistryException;
-import org.onlab.onos.of.controller.impl.registry.IControllerRegistry.ControlChangeCallback;
-import org.onlab.onos.of.controller.impl.util.Dpid;
-import org.onlab.onos.of.controller.impl.util.DummySwitchForTesting;
-import org.onlab.onos.of.controller.impl.util.InstanceId;
-import org.onlab.onos.of.controller.impl.IOFSwitch;
-import org.onlab.onos.of.controller.impl.IOFSwitch.PortChangeType;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
 import org.jboss.netty.bootstrap.ServerBootstrap;
 import org.jboss.netty.channel.ChannelPipelineFactory;
 import org.jboss.netty.channel.group.ChannelGroup;
 import org.jboss.netty.channel.group.DefaultChannelGroup;
 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
+import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
+import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFFactories;
 import org.projectfloodlight.openflow.protocol.OFFactory;
-import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.protocol.OFVersion;
-import org.projectfloodlight.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,7 +44,6 @@
  * The main controller class.  Handles all setup and network listeners
  * - Distributed ownership control of switch through IControllerRegistryService
  */
-@Component(immediate = true)
 public class Controller {
 
     protected static final Logger log = LoggerFactory.getLogger(Controller.class);
@@ -78,189 +52,33 @@
     protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
     protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
 
-    // connectedSwitches cache contains all connected switch's channelHandlers
-    // including ones where this controller is a master/equal/slave controller
-    // as well as ones that have not been activated yet
-    protected ConcurrentHashMap<Long, OFChannelHandler> connectedSwitches;
-    // These caches contains only those switches that are active
-    protected ConcurrentHashMap<Long, IOFSwitch> activeMasterSwitches;
-    protected ConcurrentHashMap<Long, IOFSwitch> activeEqualSwitches;
-    // lock to synchronize on, when manipulating multiple caches above
-    private Object multiCacheLock;
+
 
     // The controllerNodeIPsCache maps Controller IDs to their IP address.
     // It's only used by handleControllerNodeIPsChanged
     protected HashMap<String, String> controllerNodeIPsCache;
 
-    // Module dependencies
-
-    protected IControllerRegistry registryService;
-    protected IDebugCounterService debugCounters;
-
 
     private IOFSwitchManager switchManager;
 
+    private ChannelGroup cg;
+
     // Configuration options
     protected int openFlowPort = 6633;
     protected int workerThreads = 0;
 
-    // defined counters
-    private Counters counters;
-
     // Start time of the controller
     protected long systemStartTime;
 
     // Flag to always flush flow table on switch reconnect (HA or otherwise)
     protected boolean alwaysClearFlowsOnSwAdd = false;
-    private InstanceId instanceId;
+    private OpenFlowSwitchAgent agent;
 
     // Perf. related configuration
     protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
     protected static final int BATCH_MAX_SIZE = 100;
     protected static final boolean ALWAYS_DECODE_ETH = true;
 
-    protected boolean addConnectedSwitch(long dpid, OFChannelHandler h) {
-        if (connectedSwitches.get(dpid) != null) {
-            log.error("Trying to add connectedSwitch but found a previous "
-                    + "value for dpid: {}", dpid);
-            return false;
-        } else {
-            log.error("Added switch {}", dpid);
-            connectedSwitches.put(dpid, h);
-            return true;
-        }
-    }
-
-    private boolean validActivation(long dpid) {
-        if (connectedSwitches.get(dpid) == null) {
-            log.error("Trying to activate switch but is not in "
-                    + "connected switches: dpid {}. Aborting ..",
-                    HexString.toHexString(dpid));
-            return false;
-        }
-        if (activeMasterSwitches.get(dpid) != null ||
-                activeEqualSwitches.get(dpid) != null) {
-            log.error("Trying to activate switch but it is already "
-                    + "activated: dpid {}. Found in activeMaster: {} "
-                    + "Found in activeEqual: {}. Aborting ..", new Object[] {
-                            HexString.toHexString(dpid),
-                            (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
-                            (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
-            counters.switchWithSameDpidActivated.updateCounterWithFlush();
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Called when a switch is activated, with this controller's role as MASTER.
-     */
-    protected boolean addActivatedMasterSwitch(long dpid, IOFSwitch sw) {
-        synchronized (multiCacheLock) {
-            if (!validActivation(dpid)) {
-                return false;
-            }
-            activeMasterSwitches.put(dpid, sw);
-        }
-        //update counters and events
-        counters.switchActivated.updateCounterWithFlush();
-
-        return true;
-    }
-
-    /**
-     * Called when a switch is activated, with this controller's role as EQUAL.
-     */
-    protected boolean addActivatedEqualSwitch(long dpid, IOFSwitch sw) {
-        synchronized (multiCacheLock) {
-            if (!validActivation(dpid)) {
-                return false;
-            }
-            activeEqualSwitches.put(dpid, sw);
-        }
-        //update counters and events
-        counters.switchActivated.updateCounterWithFlush();
-        return true;
-    }
-
-    /**
-     * Called when this controller's role for a switch transitions from equal
-     * to master. For 1.0 switches, we internally refer to the role 'slave' as
-     * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
-     */
-    protected void transitionToMasterSwitch(long dpid) {
-        synchronized (multiCacheLock) {
-            IOFSwitch sw = activeEqualSwitches.remove(dpid);
-            if (sw == null) {
-                log.error("Transition to master called on sw {}, but switch "
-                        + "was not found in controller-cache", dpid);
-                return;
-            }
-            activeMasterSwitches.put(dpid, sw);
-        }
-    }
-
-
-    /**
-     * Called when this controller's role for a switch transitions to equal.
-     * For 1.0 switches, we internally refer to the role 'slave' as
-     * 'equal'.
-     */
-    protected void transitionToEqualSwitch(long dpid) {
-        synchronized (multiCacheLock) {
-            IOFSwitch sw = activeMasterSwitches.remove(dpid);
-            if (sw == null) {
-                log.error("Transition to equal called on sw {}, but switch "
-                        + "was not found in controller-cache", dpid);
-                return;
-            }
-            activeEqualSwitches.put(dpid, sw);
-        }
-
-    }
-
-    /**
-     * Clear all state in controller switch maps for a switch that has
-     * disconnected from the local controller. Also release control for
-     * that switch from the global repository. Notify switch listeners.
-     */
-    protected void removeConnectedSwitch(long dpid) {
-        releaseRegistryControl(dpid);
-        connectedSwitches.remove(dpid);
-        IOFSwitch sw = activeMasterSwitches.remove(dpid);
-        if (sw == null) {
-            sw = activeEqualSwitches.remove(dpid);
-        }
-        if (sw != null) {
-            sw.cancelAllStatisticsReplies();
-            sw.setConnected(false); // do we need this?
-        }
-        counters.switchDisconnected.updateCounterWithFlush();
-
-    }
-
-    /**
-     * Indicates that ports on the given switch have changed. Enqueue a
-     * switch update.
-     * @param dpid
-     * @param port
-     * @param changeType
-     */
-    protected void notifyPortChanged(long dpid, OFPortDesc port,
-            PortChangeType changeType) {
-        if (port == null || changeType == null) {
-            String msg = String.format("Switch port or changetType must not "
-                    + "be null in port change notification");
-            throw new NullPointerException(msg);
-        }
-        if (connectedSwitches.get(dpid) == null || getSwitch(dpid) == null) {
-            log.warn("Port change update on switch {} not connected or activated "
-                    + "... Aborting.", HexString.toHexString(dpid));
-            return;
-        }
-
-    }
-
     // ***************
     // Getters/Setters
     // ***************
@@ -268,180 +86,8 @@
 
     public synchronized void setIOFSwitchManager(IOFSwitchManager swManager) {
         this.switchManager = swManager;
-        this.registryService = swManager.getRegistry();
     }
 
-
-    public void setDebugCounter(IDebugCounterService dcs) {
-        this.debugCounters = dcs;
-    }
-
-    IDebugCounterService getDebugCounter() {
-        return this.debugCounters;
-    }
-
-    // **********************
-    // Role Handling
-    // **********************
-
-    /**
-     * created by ONOS - works with registry service.
-     */
-    protected class RoleChangeCallback implements ControlChangeCallback {
-        @Override
-        public void controlChanged(long dpidLong, boolean hasControl) {
-            Dpid dpid = new Dpid(dpidLong);
-            log.info("Role change callback for switch {}, hasControl {}",
-                    dpid, hasControl);
-
-            Role role = null;
-
-            /*
-             * issue #229
-             * Cannot rely on sw.getRole() as it can be behind due to pending
-             * role changes in the queue. Just submit it and late the
-             * RoleChanger handle duplicates.
-             */
-
-            if (hasControl) {
-                role = Role.MASTER;
-            } else {
-                role = Role.EQUAL; // treat the same as Role.SLAVE
-            }
-
-            OFChannelHandler swCh = connectedSwitches.get(dpid.value());
-            if (swCh == null) {
-                log.warn("Switch {} not found in connected switches", dpid);
-                return;
-            }
-
-            log.debug("Sending role request {} msg to {}", role, dpid);
-            swCh.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE);
-        }
-    }
-
-    /**
-     * Submit request to the registry service for mastership of the
-     * switch.
-     * @param dpid this datapath to get role for
-     */
-    public synchronized void submitRegistryRequest(long dpid) {
-        if (registryService == null) {
-            /*
-             * If we have no registry then simply assign
-             * mastership to this controller.
-             */
-            new RoleChangeCallback().controlChanged(dpid, true);
-            return;
-        }
-        OFChannelHandler h = connectedSwitches.get(dpid);
-        if (h == null) {
-            log.error("Trying to request registry control for switch {} "
-                    + "not in connected switches. Aborting.. ",
-                    HexString.toHexString(dpid));
-            connectedSwitches.get(dpid).disconnectSwitch();
-            return;
-        }
-        //Request control of the switch from the global registry
-        try {
-            h.controlRequested = Boolean.TRUE;
-            registryService.requestControl(dpid, new RoleChangeCallback());
-        } catch (RegistryException e) {
-            log.debug("Registry error: {}", e.getMessage());
-            h.controlRequested = Boolean.FALSE;
-        }
-        if (!h.controlRequested) { // XXX what is being attempted here?
-            // yield to allow other thread(s) to release control
-            // TODO AAS: this is awful and needs to be fixed
-            Thread.yield();
-            // safer to bounce the switch to reconnect here than proceeding further
-            // XXX S why? can't we just try again a little later?
-            log.debug("Closing sw:{} because we weren't able to request control " +
-                    "successfully" + dpid);
-            connectedSwitches.get(dpid).disconnectSwitch();
-        }
-    }
-
-    /**
-     * Relinquish role for the switch.
-     * @param dpidLong the controlled datapath
-     */
-    public synchronized void releaseRegistryControl(long dpidLong) {
-        OFChannelHandler h = connectedSwitches.get(dpidLong);
-        if (h == null) {
-            log.error("Trying to release registry control for switch {} "
-                    + "not in connected switches. Aborting.. ",
-                    HexString.toHexString(dpidLong));
-            return;
-        }
-        if (registryService != null && h.controlRequested) {
-            //TODO the above is not good for testing need to change controlrequest to method call.
-            registryService.releaseControl(dpidLong);
-        }
-    }
-
-
-    // FIXME: remove this method
-    public Map<Long, IOFSwitch> getSwitches() {
-        return getMasterSwitches();
-    }
-
-    // FIXME: remove this method
-    public Map<Long, IOFSwitch> getMasterSwitches() {
-        return Collections.unmodifiableMap(activeMasterSwitches);
-    }
-
-
-
-    public Set<Long> getAllSwitchDpids() {
-        Set<Long> dpids = new HashSet<Long>();
-        dpids.addAll(activeMasterSwitches.keySet());
-        dpids.addAll(activeEqualSwitches.keySet());
-        return dpids;
-    }
-
-
-    public Set<Long> getAllMasterSwitchDpids() {
-        Set<Long> dpids = new HashSet<Long>();
-        dpids.addAll(activeMasterSwitches.keySet());
-        return dpids;
-    }
-
-
-    public Set<Long> getAllEqualSwitchDpids() {
-        Set<Long> dpids = new HashSet<Long>();
-        dpids.addAll(activeEqualSwitches.keySet());
-        return dpids;
-    }
-
-
-    public IOFSwitch getSwitch(long dpid) {
-        IOFSwitch sw = null;
-        sw = activeMasterSwitches.get(dpid);
-        if (sw != null) {
-            return sw;
-        }
-        sw = activeEqualSwitches.get(dpid);
-        if (sw != null) {
-            return sw;
-        }
-        return sw;
-    }
-
-
-    public IOFSwitch getMasterSwitch(long dpid) {
-        return  activeMasterSwitches.get(dpid);
-    }
-
-
-    public IOFSwitch getEqualSwitch(long dpid) {
-        return  activeEqualSwitches.get(dpid);
-    }
-
-
-
-
-
     public OFFactory getOFMessageFactory10() {
         return FACTORY10;
     }
@@ -469,12 +115,6 @@
         return (this.systemStartTime);
     }
 
-
-    public InstanceId getInstanceId() {
-        return instanceId;
-    }
-
-
     // **************
     // Initialization
     // **************
@@ -509,7 +149,7 @@
                     new OpenflowPipelineFactory(this, null);
             bootstrap.setPipelineFactory(pfact);
             InetSocketAddress sa = new InetSocketAddress(openFlowPort);
-            final ChannelGroup cg = new DefaultChannelGroup();
+            cg = new DefaultChannelGroup();
             cg.add(bootstrap.bind(sa));
 
             log.info("Listening for switch connections on {}", sa);
@@ -544,20 +184,6 @@
             this.workerThreads = Integer.parseInt(threads);
         }
         log.debug("Number of worker threads set to {}", this.workerThreads);
-        String controllerId = configParams.get("controllerid");
-        if (controllerId != null) {
-            this.instanceId = new InstanceId(controllerId);
-        } else {
-            //Try to get the hostname of the machine and use that for controller ID
-            try {
-                String hostname = java.net.InetAddress.getLocalHost().getHostName();
-                this.instanceId = new InstanceId(hostname);
-            } catch (UnknownHostException e) {
-                log.warn("Can't get hostname, using the default");
-            }
-        }
-
-        log.debug("ControllerId set to {}", this.instanceId);
     }
 
 
@@ -567,16 +193,11 @@
     public void init(Map<String, String> configParams) {
         // These data structures are initialized here because other
         // module's startUp() might be called before ours
-        this.activeMasterSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
-        this.activeEqualSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
-        this.connectedSwitches = new ConcurrentHashMap<Long, OFChannelHandler>();
         this.controllerNodeIPsCache = new HashMap<String, String>();
 
         setConfigParams(configParams);
         this.systemStartTime = System.currentTimeMillis();
-        this.setDebugCounter(new DebugCounter());
-        this.counters = new Counters();
-        this.multiCacheLock = new Object();
+
 
     }
 
@@ -589,215 +210,10 @@
                     "that the system database has failed to start. " +
                     LogMessageDoc.CHECK_CONTROLLER)
     public synchronized void startupComponents() {
-        try {
-            if (registryService != null) {
-                registryService.registerController(instanceId.toString());
-            }
-        } catch (RegistryException e) {
-            log.warn("Registry service error: {}", e.getMessage());
-        }
-
-        // register counters and events
-        try {
-            this.counters.createCounters(debugCounters);
-        } catch (CounterException e) {
-            log.warn("Counters unavailable: {}", e.getMessage());
-        }
+        //TODO do something maybe
     }
 
     // **************
-    // debugCounter registrations
-    // **************
-
-    public static class Counters {
-        public static final String PREFIX = "controller";
-        public IDebugCounter switchActivated;
-        public IDebugCounter switchWithSameDpidActivated; // warn
-        public IDebugCounter switchDisconnected;
-        public IDebugCounter messageReceived;
-        public IDebugCounter switchDisconnectReadTimeout;
-        public IDebugCounter switchDisconnectHandshakeTimeout;
-        public IDebugCounter switchDisconnectIOError;
-        public IDebugCounter switchDisconnectParseError;
-        public IDebugCounter switchDisconnectSwitchStateException;
-        public IDebugCounter rejectedExecutionException;
-        public IDebugCounter switchDisconnectOtherException;
-        public IDebugCounter switchConnected;
-        public IDebugCounter unhandledMessage;
-        public IDebugCounter packetInWhileSwitchIsSlave;
-        public IDebugCounter epermErrorWhileSwitchIsMaster;
-        public IDebugCounter roleReplyTimeout;
-        public IDebugCounter roleReplyReceived; // expected RoleReply received
-        public IDebugCounter roleReplyErrorUnsupported;
-        public IDebugCounter switchCounterRegistrationFailed;
-
-        void createCounters(IDebugCounterService debugCounters) throws CounterException {
-
-            switchActivated =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-activated",
-                            "A switch connected to this controller is now " +
-                            "in MASTER role",
-                            CounterType.ALWAYS_COUNT);
-
-            switchWithSameDpidActivated = // warn
-                debugCounters.registerCounter(
-                            PREFIX, "switch-with-same-dpid-activated",
-                            "A switch with the same DPID as another switch " +
-                            "connected to the controller. This can be " +
-                            "caused by multiple switches configured with " +
-                            "the same DPID or by a switch reconnecting very " +
-                            "quickly.",
-                            CounterType.COUNT_ON_DEMAND,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            switchDisconnected =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-disconnected",
-                            "FIXME: switch has disconnected",
-                            CounterType.ALWAYS_COUNT);
-
-        //------------------------
-        // channel handler counters. Factor them out ??
-            messageReceived =
-                debugCounters.registerCounter(
-                            PREFIX, "message-received",
-                            "Number of OpenFlow messages received. Some of " +
-                            "these might be throttled",
-                            CounterType.ALWAYS_COUNT);
-
-            switchDisconnectReadTimeout =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-disconnect-read-timeout",
-                            "Number of times a switch was disconnected due " +
-                            "due the switch failing to send OpenFlow " +
-                            "messages or responding to OpenFlow ECHOs",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            switchDisconnectHandshakeTimeout =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-disconnect-handshake-timeout",
-                            "Number of times a switch was disconnected " +
-                            "because it failed to complete the handshake " +
-                            "in time.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            switchDisconnectIOError =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-disconnect-io-error",
-                            "Number of times a switch was disconnected " +
-                            "due to IO errors on the switch connection.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            switchDisconnectParseError =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-disconnect-parse-error",
-                           "Number of times a switch was disconnected " +
-                           "because it sent an invalid packet that could " +
-                           "not be parsed",
-                           CounterType.ALWAYS_COUNT,
-                           IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchDisconnectSwitchStateException =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-disconnect-switch-state-exception",
-                            "Number of times a switch was disconnected " +
-                            "because it sent messages that were invalid " +
-                            "given the switch connection's state.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            rejectedExecutionException =
-                debugCounters.registerCounter(
-                            PREFIX, "rejected-execution-exception",
-                            "TODO",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchDisconnectOtherException =
-                debugCounters.registerCounter(
-                            PREFIX,  "switch-disconnect-other-exception",
-                            "Number of times a switch was disconnected " +
-                            "due to an exceptional situation not covered " +
-                            "by other counters",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchConnected =
-                debugCounters.registerCounter(
-                            PREFIX, "switch-connected",
-                            "Number of times a new switch connection was " +
-                            "established",
-                            CounterType.ALWAYS_COUNT);
-
-            unhandledMessage =
-                debugCounters.registerCounter(
-                            PREFIX, "unhandled-message",
-                            "Number of times an OpenFlow message was " +
-                            "received that the controller ignored because " +
-                            "it was inapproriate given the switch " +
-                            "connection's state.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-                            // might be less than warning
-
-            packetInWhileSwitchIsSlave =
-                debugCounters.registerCounter(
-                            PREFIX, "packet-in-while-switch-is-slave",
-                            "Number of times a packet in was received " +
-                            "from a switch that was in SLAVE role. " +
-                            "Possibly inidicates inconsistent roles.",
-                            CounterType.ALWAYS_COUNT);
-            epermErrorWhileSwitchIsMaster =
-                debugCounters.registerCounter(
-                            PREFIX, "eperm-error-while-switch-is-master",
-                            "Number of times a permission error was " +
-                            "received while the switch was in MASTER role. " +
-                            "Possibly inidicates inconsistent roles.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            roleReplyTimeout =
-                debugCounters.registerCounter(
-                            PREFIX, "role-reply-timeout",
-                            "Number of times a role request message did not " +
-                            "receive the expected reply from a switch",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            roleReplyReceived = // expected RoleReply received
-                debugCounters.registerCounter(
-                            PREFIX, "role-reply-received",
-                            "Number of times the controller received the " +
-                            "expected role reply message from a switch",
-                            CounterType.ALWAYS_COUNT);
-
-            roleReplyErrorUnsupported =
-                debugCounters.registerCounter(
-                            PREFIX, "role-reply-error-unsupported",
-                            "Number of times the controller received an " +
-                            "error from a switch in response to a role " +
-                            "request indicating that the switch does not " +
-                            "support roles.",
-                            CounterType.ALWAYS_COUNT);
-
-            switchCounterRegistrationFailed =
-                    debugCounters.registerCounter(PREFIX,
-                                "switch-counter-registration-failed",
-                                "Number of times the controller failed to " +
-                                "register per-switch debug counters",
-                                CounterType.ALWAYS_COUNT,
-                                IDebugCounterService.CTR_MDATA_WARN);
-
-
-        }
-    }
-
-    public Counters getCounters() {
-        return this.counters;
-    }
-
-
-    // **************
     // Utility methods
     // **************
 
@@ -820,20 +236,24 @@
      * @param desc
      * @return switch instance
      */
-    protected IOFSwitch getOFSwitchInstance(OFDescStatsReply desc, OFVersion ofv) {
-        if (switchManager == null) {
-            return new DummySwitchForTesting();
-        }
-        return switchManager.getSwitchImpl(desc.getMfrDesc(), desc.getHwDesc(),
+    protected AbstractOpenFlowSwitch getOFSwitchInstance(OFDescStatsReply desc, OFVersion ofv) {
+        AbstractOpenFlowSwitch sw =  switchManager.getSwitchImpl(desc.getMfrDesc(), desc.getHwDesc(),
                                             desc.getSwDesc(), ofv);
+        sw.setAgent(agent);
+        return sw;
     }
 
-    @Activate
-    public void activate() {
+    public void start(OpenFlowSwitchAgent ag) {
         log.info("Initialising OpenFlow Lib and IO");
+        this.agent = ag;
         this.init(new HashMap<String, String>());
         this.startupComponents();
         this.run();
     }
 
+
+    public void stop() {
+        cg.close();
+    }
+
 }
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/IOFSwitchManager.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
similarity index 61%
rename from of/ctl/src/main/java/org/onlab/onos/of/controller/impl/IOFSwitchManager.java
rename to of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
index 0acb321..4b2f7c3 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/IOFSwitchManager.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
@@ -1,8 +1,7 @@
-package org.onlab.onos.of.controller.impl;
+package org.onlab.onos.of.controller.impl.internal;
 
 import org.projectfloodlight.openflow.protocol.OFVersion;
 
-import org.onlab.onos.of.controller.impl.registry.IControllerRegistry;
 
 /**
  * Interface to passed to controller class in order to allow
@@ -22,12 +21,6 @@
      * @param ofv openflow version
      * @return A switch of type IOFSwitch.
      */
-    public IOFSwitch getSwitchImpl(String mfr, String hwDesc, String swDesc, OFVersion ofv);
-
-    /**
-     * Returns the mastership registry used during controller-switch role election.
-     * @return the registry
-     */
-    public IControllerRegistry getRegistry();
+    public AbstractOpenFlowSwitch getSwitchImpl(String mfr, String hwDesc, String swDesc, OFVersion ofv);
 
 }
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
index 667a051..5db1fc3 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandler.java
@@ -4,21 +4,11 @@
 import java.io.IOException;
 import java.nio.channels.ClosedChannelException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.RejectedExecutionException;
 
-import org.onlab.onos.of.controller.impl.IOFSwitch;
-import org.onlab.onos.of.controller.impl.IOFSwitch.PortChangeEvent;
-import org.onlab.onos.of.controller.impl.Role;
-import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
-import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService.CounterException;
-import org.onlab.onos.of.controller.impl.internal.Controller.Counters;
-import org.onlab.onos.of.controller.impl.internal.OFChannelHandler.ChannelState.RoleReplyInfo;
-
 import org.jboss.netty.channel.Channel;
 import org.jboss.netty.channel.ChannelHandlerContext;
 import org.jboss.netty.channel.ChannelStateEvent;
@@ -27,12 +17,14 @@
 import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
 import org.jboss.netty.handler.timeout.IdleStateEvent;
 import org.jboss.netty.handler.timeout.ReadTimeoutException;
+import org.onlab.onos.of.controller.RoleState;
+import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
+import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
 import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
 import org.projectfloodlight.openflow.protocol.OFBarrierReply;
 import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
-import org.projectfloodlight.openflow.protocol.OFControllerRole;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFDescStatsRequest;
 import org.projectfloodlight.openflow.protocol.OFEchoReply;
@@ -49,15 +41,12 @@
 import org.projectfloodlight.openflow.protocol.OFHello;
 import org.projectfloodlight.openflow.protocol.OFHelloElem;
 import org.projectfloodlight.openflow.protocol.OFMessage;
-import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
-import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply;
 import org.projectfloodlight.openflow.protocol.OFPacketIn;
 import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFPortDescStatsRequest;
 import org.projectfloodlight.openflow.protocol.OFPortStatus;
 import org.projectfloodlight.openflow.protocol.OFQueueGetConfigReply;
 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;
@@ -66,11 +55,10 @@
 import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
 import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
-import org.projectfloodlight.openflow.protocol.errormsg.OFRoleRequestFailedErrorMsg;
 import org.projectfloodlight.openflow.types.U32;
-import org.projectfloodlight.openflow.types.U64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 /**
  * Channel handler deals with the switch connection and dispatches
  * switch messages to the appropriate locations.
@@ -79,18 +67,13 @@
     private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
     private static final long DEFAULT_ROLE_TIMEOUT_MS = 2 * 1000; // 10 sec
     private final Controller controller;
-    private final Counters counters;
-    private IOFSwitch sw;
+    private AbstractOpenFlowSwitch sw;
     private long thisdpid; // channelHandler cached value of connected switch id
     private Channel channel;
     // State needs to be volatile because the HandshakeTimeoutHandler
     // needs to check if the handshake is complete
     private volatile ChannelState state;
 
-    // All role messaging is handled by the roleChanger. The channel state machine
-    // coordinates between the roleChanger and the controller-global-registry-service
-    // to determine controller roles per switch.
-    private RoleChanger roleChanger;
     // Used to coordinate between the controller and the cleanup thread(?)
     // for access to the global registry on a per switch basis.
     volatile Boolean controlRequested;
@@ -125,8 +108,6 @@
      */
     OFChannelHandler(Controller controller) {
         this.controller = controller;
-        this.counters = controller.getCounters();
-        this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_MS);
         this.state = ChannelState.INIT;
         this.pendingPortStatusMsg = new CopyOnWriteArrayList<OFPortStatus>();
         factory13 = controller.getOFMessageFactory13();
@@ -135,392 +116,14 @@
         duplicateDpidFound = Boolean.FALSE;
     }
 
-    //*******************
-    //  Role Handling
-    //*******************
 
-    /**
-     * When we remove a pending role request we use this enum to indicate how we
-     * arrived at the decision. When we send a role request to the switch, we
-     * also use  this enum to indicate what we expect back from the switch, so the
-     * role changer can match the reply to our expectation.
-     */
-    public enum RoleRecvStatus {
-        /** The switch returned an error indicating that roles are not.
-         * supported*/
-        UNSUPPORTED,
-        /** The request timed out. */
-        NO_REPLY,
-        /** The reply was old, there is a newer request pending. */
-        OLD_REPLY,
-        /**
-         *  The reply's role matched the role that this controller set in the
-         *  request message - invoked either initially at startup or to reassert
-         *  current role.
-         */
-        MATCHED_CURRENT_ROLE,
-        /**
-         *  The reply's role matched the role that this controller set in the
-         *  request message - this is the result of a callback from the
-         *  global registry, followed by a role request sent to the switch.
-         */
-        MATCHED_SET_ROLE,
-        /**
-         * The reply's role was a response to the query made by this controller.
-         */
-        REPLY_QUERY,
-        /** We received a role reply message from the switch
-         *  but the expectation was unclear, or there was no expectation.
-         */
-        OTHER_EXPECTATION,
-    }
-
-    /**
-     * Forwards to RoleChanger. See there.
-     * @param role
-     */
-    public void sendRoleRequest(Role role, RoleRecvStatus expectation) {
-        try {
-            roleChanger.sendRoleRequest(role, expectation);
-        } catch (IOException e) {
-            log.error("Disconnecting switch {} due to IO Error: {}",
-                    getSwitchInfoString(), e.getMessage());
-            channel.close();
-        }
-    }
 
     // XXX S consider if necessary
     public void disconnectSwitch() {
         sw.disconnectSwitch();
     }
 
-    /**
-     * 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.
-     */
-    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 int pendingXid;
-        // the role that's pending
-        private Role pendingRole;
-        // system time in MS when we send the request
-        private long roleSubmitTime;
-        // the timeout to use
-        private final long roleTimeoutMs;
-        // the expectation set by the caller for the returned role
-        private RoleRecvStatus expectation;
 
-        public RoleChanger(long roleTimeoutMs) {
-            this.requestPending = false;
-            this.roleSubmitTime = 0;
-            this.pendingXid = -1;
-            this.pendingRole = null;
-            this.roleTimeoutMs = roleTimeoutMs;
-            this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE;
-        }
-
-        /**
-         * Send NX role request message to the switch requesting the specified
-         * role.
-         *
-         * @param sw switch to send the role request message to
-         * @param role role to request
-         */
-        private int sendNxRoleRequest(Role role) throws IOException {
-            // Convert the role enum to the appropriate role to send
-            OFNiciraControllerRole roleToSend = OFNiciraControllerRole.ROLE_OTHER;
-            switch (role) {
-            case MASTER:
-                roleToSend = OFNiciraControllerRole.ROLE_MASTER;
-                break;
-            case SLAVE:
-            case EQUAL:
-            default:
-                // ensuring that the only two roles sent to 1.0 switches with
-                // Nicira role support, are MASTER and SLAVE
-                roleToSend = OFNiciraControllerRole.ROLE_SLAVE;
-                log.warn("Sending Nx Role.SLAVE to switch {}.", sw);
-            }
-            int xid = sw.getNextTransactionId();
-            OFExperimenter roleRequest = factory10
-                    .buildNiciraControllerRoleRequest()
-                    .setXid(xid)
-                    .setRole(roleToSend)
-                    .build();
-            sw.write(Collections.<OFMessage>singletonList(roleRequest));
-            return xid;
-        }
-
-        private int sendOF13RoleRequest(Role role) throws IOException {
-            // Convert the role enum to the appropriate role to send
-            OFControllerRole roleToSend = OFControllerRole.ROLE_NOCHANGE;
-            switch (role) {
-            case EQUAL:
-                roleToSend = OFControllerRole.ROLE_EQUAL;
-                break;
-            case MASTER:
-                roleToSend = OFControllerRole.ROLE_MASTER;
-                break;
-            case SLAVE:
-                roleToSend = OFControllerRole.ROLE_SLAVE;
-                break;
-            default:
-                log.warn("Sending default role.noChange to switch {}."
-                        + " Should only be used for queries.", sw);
-            }
-
-            int xid = sw.getNextTransactionId();
-            OFRoleRequest rrm = factory13
-                    .buildRoleRequest()
-                    .setRole(roleToSend)
-                    .setXid(xid)
-                    .setGenerationId(sw.getNextGenerationId())
-                    .build();
-            sw.write(rrm);
-            return xid;
-        }
-
-        /**
-         * Send a role request with the given role to the switch and update
-         * the pending request and timestamp.
-         * Sends an OFPT_ROLE_REQUEST to an OF1.3 switch, OR
-         * Sends an NX_ROLE_REQUEST to an OF1.0 switch if configured to support it
-         * in the IOFSwitch driver. If not supported, this method sends nothing
-         * and returns 'false'. The caller should take appropriate action.
-         *
-         * One other optimization we do here is that for OF1.0 switches with
-         * Nicira role message support, we force the Role.EQUAL to become
-         * Role.SLAVE, as there is no defined behavior for the Nicira role OTHER.
-         * We cannot expect it to behave like SLAVE. We don't have this problem with
-         * OF1.3 switches, because Role.EQUAL is well defined and we can simulate
-         * SLAVE behavior by using ASYNC messages.
-         *
-         * @param role
-         * @throws IOException
-         * @returns false if and only if the switch does not support role-request
-         * messages, according to the switch driver; true otherwise.
-         */
-        synchronized boolean sendRoleRequest(Role role, RoleRecvStatus exp)
-                throws IOException {
-            this.expectation = exp;
-
-            if (ofVersion == OFVersion.OF_10) {
-                Boolean supportsNxRole = (Boolean)
-                        sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE);
-                if (!supportsNxRole) {
-                    log.debug("Switch driver indicates no support for Nicira "
-                            + "role request messages. Not sending ...");
-                    state.handleUnsentRoleMessage(OFChannelHandler.this, role,
-                            expectation);
-                    return false;
-                }
-                // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn.
-                // make Role.EQUAL become Role.SLAVE
-                role = (role == Role.EQUAL) ? Role.SLAVE : role;
-                pendingXid = sendNxRoleRequest(role);
-                pendingRole = role;
-                roleSubmitTime = System.currentTimeMillis();
-                requestPending = true;
-            } else {
-                // OF1.3 switch, use OFPT_ROLE_REQUEST message
-                pendingXid = sendOF13RoleRequest(role);
-                pendingRole = role;
-                roleSubmitTime = System.currentTimeMillis();
-                requestPending = true;
-            }
-            return true;
-        }
-
-        /**
-         * Deliver a received role reply.
-         *
-         * 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, and
-         * return
-         *
-         * If no request is pending we disconnect with a SwitchStateException
-         *
-         * @param RoleReplyInfo information about role-reply in format that
-         *                      controller can understand.
-         * @throws SwitchStateException if no request is pending
-         */
-        synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
-                throws SwitchStateException {
-            if (!requestPending) {
-                Role currentRole = (sw != null) ? sw.getRole() : null;
-                if (currentRole != null) {
-                    if (currentRole == rri.getRole()) {
-                        // Don't disconnect if the role reply we received is
-                        // for the same role we are already in.
-                        log.debug("Received unexpected RoleReply from "
-                                + "Switch: {} in State: {}. "
-                                + "Role in reply is same as current role of this "
-                                + "controller for this sw. Ignoring ...",
-                                getSwitchInfoString(), state.toString());
-                        return RoleRecvStatus.OTHER_EXPECTATION;
-                    } else {
-                        String msg = String.format("Switch: [%s], State: [%s], "
-                                + "received unexpected RoleReply[%s]. "
-                                + "No roles are pending, and this controller's "
-                                + "current role:[%s] does not match reply. "
-                                + "Disconnecting switch ... ",
-                                OFChannelHandler.this.getSwitchInfoString(),
-                                OFChannelHandler.this.state.toString(),
-                                rri, currentRole);
-                        throw new SwitchStateException(msg);
-                    }
-                }
-                log.debug("Received unexpected RoleReply {} from "
-                        + "Switch: {} in State: {}. "
-                        + "This controller has no current role for this sw. "
-                        + "Ignoring ...", new Object[] {rri,
-                                getSwitchInfoString(), state});
-                return RoleRecvStatus.OTHER_EXPECTATION;
-            }
-
-            int xid = (int) rri.getXid();
-            Role role = rri.getRole();
-            // XXX S should check generation id meaningfully and other cases of expectations
-            // U64 genId = rri.getGenId();
-
-            if (pendingXid != xid) {
-                log.debug("Received older role reply from " +
-                        "switch {} ({}). Ignoring. " +
-                        "Waiting for {}, xid={}",
-                        new Object[] {getSwitchInfoString(), rri,
-                        pendingRole, pendingXid });
-                return RoleRecvStatus.OLD_REPLY;
-            }
-
-            if (pendingRole == role) {
-                log.debug("Received role reply message from {} that matched "
-                        + "expected role-reply {} with expectations {}",
-                        new Object[] {getSwitchInfoString(), role, expectation});
-                counters.roleReplyReceived.updateCounterWithFlush();
-                //setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY); dont want to set state here
-                if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE ||
-                        expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
-                    return expectation;
-                } else {
-                    return RoleRecvStatus.OTHER_EXPECTATION;
-                }
-            }
-
-            // if xids match but role's don't, perhaps its a query (OF1.3)
-            if (expectation == RoleRecvStatus.REPLY_QUERY) {
-                return expectation;
-            }
-
-            return RoleRecvStatus.OTHER_EXPECTATION;
-        }
-
-        /**
-         * Called if we receive an  error message. If the xid matches the
-         * pending request we handle it otherwise we ignore it.
-         *
-         * 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
-         */
-        synchronized RoleRecvStatus deliverError(OFErrorMsg error)
-                throws SwitchStateException {
-            if (!requestPending) {
-                log.debug("Received an error msg from sw {}, but no pending "
-                        + "requests in role-changer; not handling ...",
-                        getSwitchInfoString());
-                return RoleRecvStatus.OTHER_EXPECTATION;
-            }
-            if (pendingXid != error.getXid()) {
-                if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
-                    log.debug("Received an error msg from sw {} for a role request,"
-                            + " but not for pending request in role-changer; "
-                            + " ignoring error {} ...",
-                            getSwitchInfoString(), error);
-                }
-                return RoleRecvStatus.OTHER_EXPECTATION;
-            }
-            // it is an error related to a currently pending role request message
-            if (error.getErrType() == OFErrorType.BAD_REQUEST) {
-                counters.roleReplyErrorUnsupported.updateCounterWithFlush();
-                log.error("Received a error msg {} from sw {} in state {} for "
-                        + "pending role request {}. Switch driver indicates "
-                        + "role-messaging is supported. Possible issues in "
-                        + "switch driver configuration?", new Object[] {
-                                ((OFBadRequestErrorMsg) error).toString(),
-                                getSwitchInfoString(), state, pendingRole
-                        });
-                return RoleRecvStatus.UNSUPPORTED;
-            }
-
-            if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
-                OFRoleRequestFailedErrorMsg rrerr =
-                        (OFRoleRequestFailedErrorMsg) error;
-                switch (rrerr.getCode()) {
-                case BAD_ROLE:
-                    // switch says that current-role-req has bad role?
-                    // for now we disconnect
-                    // fall-thru
-                case STALE:
-                    // switch says that current-role-req has stale gen-id?
-                    // for now we disconnect
-                    // fall-thru
-                case UNSUP:
-                    // switch says that current-role-req has role that
-                    // cannot be supported? for now we disconnect
-                    String msgx = String.format("Switch: [%s], State: [%s], "
-                            + "received Error to for pending role request [%s]. "
-                            + "Error:[%s]. Disconnecting switch ... ",
-                            OFChannelHandler.this.getSwitchInfoString(),
-                            OFChannelHandler.this.state.toString(),
-                            pendingRole, rrerr);
-                    throw new SwitchStateException(msgx);
-                default:
-                    break;
-                }
-            }
-
-            // This error message was for a role request message but we dont know
-            // how to handle errors for nicira role request messages
-            return RoleRecvStatus.OTHER_EXPECTATION;
-        }
-
-        /**
-         * Check if a pending role request has timed out.
-         */
-        void checkTimeout() {
-            if (!requestPending) {
-                return;
-            }
-            synchronized (this) {
-                if (!requestPending) {
-                    return;
-                }
-                long now = System.currentTimeMillis();
-                if (now - roleSubmitTime > roleTimeoutMs) {
-                    // timeout triggered.
-                    counters.roleReplyTimeout.updateCounterWithFlush();
-                    //setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY);
-                    // XXX S come back to this
-                }
-            }
-        }
-
-    }
 
     //*************************
     //  Channel State Machine
@@ -628,8 +231,7 @@
                 log.info("Received features reply for switch at {} with dpid {}",
                         h.getSwitchInfoString(), h.thisdpid);
                 //update the controller about this connected switch
-                boolean success = h.controller.addConnectedSwitch(
-                        h.thisdpid, h);
+                boolean success = h.sw.addConnectedSwitch();
                 if (!success) {
                     disconnectDuplicate(h);
                     return;
@@ -825,41 +427,16 @@
                 h.sw.setConnected(true);
                 h.sw.setChannel(h.channel);
 
-                try {
-                    h.sw.setDebugCounterService(h.controller.getDebugCounter());
-                } catch (CounterException e) {
-                    h.counters.switchCounterRegistrationFailed
-                    .updateCounterNoFlush();
-                    log.warn("Could not register counters for switch {} ",
-                            h.getSwitchInfoString(), e);
-                }
 
                 log.info("Switch {} bound to class {}, description {}",
                         new Object[] {h.sw, h.sw.getClass(), drep });
                 //Put switch in EQUAL mode until we hear back from the global registry
                 log.debug("Setting new switch {} to EQUAL and sending Role request",
                         h.sw.getStringId());
-                h.setSwitchRole(Role.EQUAL);
-                try {
-                    boolean supportsRRMsg = h.roleChanger.sendRoleRequest(Role.EQUAL,
-                            RoleRecvStatus.MATCHED_CURRENT_ROLE);
-                    if (!supportsRRMsg) {
-                        log.warn("Switch {} does not support role request messages "
-                                + "of any kind. No role messages were sent. "
-                                + "This controller instance SHOULD become MASTER "
-                                + "from the registry process. ",
-                                h.getSwitchInfoString());
-                    }
-                    h.setState(WAIT_INITIAL_ROLE);
-                    // request control of switch from global registry -
-                    // necessary even if this is the only controller the
-                    // switch is connected to.
-                    h.controller.submitRegistryRequest(h.sw.getId());
-                } catch (IOException e) {
-                    log.error("Exception when sending role request: {} ",
-                            e.getMessage());
-                    // FIXME shouldn't we disconnect?
-                }
+                h.setSwitchRole(RoleState.EQUAL);
+                h.sw.startDriverHandshake();
+                h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
+
             }
 
             @Override
@@ -880,133 +457,6 @@
             }
         },
 
-        /**
-         * We are waiting for a role reply message in response to a role request
-         * sent after hearing back from the registry service -- OR -- we are
-         * just waiting to hear back from the registry service in the case that
-         * the switch does not support role messages. If completed successfully,
-         * the controller's role for this switch will be set here.
-         * Before we move to the state corresponding to the role, we allow the
-         * switch specific driver to complete its configuration. This configuration
-         * typically depends on the role the controller is playing for this switch.
-         * And so we set the switch role (for 'this' controller) before we start
-         * the driver-sub-handshake.
-         * Next State: WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
-         */
-        WAIT_INITIAL_ROLE(false) {
-            @Override
-            void processOFError(OFChannelHandler h, OFErrorMsg m)
-                    throws SwitchStateException {
-                // role changer will ignore the error if it isn't for it
-                RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
-                if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
-                    logError(h, m);
-                }
-            }
-
-            @Override
-            void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
-                    throws IOException, SwitchStateException {
-                Role role = extractNiciraRoleReply(h, m);
-                // If role == null it means the vendor (experimenter) message
-                // wasn't really a Nicira role reply. We ignore this case.
-                if (role != null) {
-                    RoleReplyInfo rri = new RoleReplyInfo(role, null, m.getXid());
-                    RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
-                    if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-                        setRoleAndStartDriverHandshake(h, rri.getRole());
-                    } // else do nothing - wait for the correct expected reply
-                } else {
-                    unhandledMessageReceived(h, m);
-                }
-            }
-
-            @Override
-            void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
-                    throws SwitchStateException, IOException {
-                RoleReplyInfo rri = extractOFRoleReply(h, m);
-                RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
-                if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-                    setRoleAndStartDriverHandshake(h, rri.getRole());
-                } // else do nothing - wait for the correct expected reply
-            }
-
-            @Override
-            void handleUnsentRoleMessage(OFChannelHandler h, Role role,
-                    RoleRecvStatus expectation) throws IOException {
-                // typically this is triggered for a switch where role messages
-                // are not supported - we confirm that the role being set is
-                // master and move to the next state
-                if (expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
-                    if (role == Role.MASTER) {
-                        setRoleAndStartDriverHandshake(h, role);
-                    } else {
-                        log.error("Expected MASTER role from registry for switch "
-                                + "which has no support for role-messages."
-                                + "Received {}. It is possible that this switch "
-                                + "is connected to other controllers, in which "
-                                + "case it should support role messages - not "
-                                + "moving forward.", role);
-                    }
-                } // else do nothing - wait to hear back from registry
-
-            }
-
-            private void setRoleAndStartDriverHandshake(OFChannelHandler h,
-                    Role role) throws IOException {
-                h.setSwitchRole(role);
-                h.sw.startDriverHandshake();
-                if (h.sw.isDriverHandshakeComplete()) {
-                    Role mySwitchRole = h.sw.getRole();
-                    if (mySwitchRole == Role.MASTER) {
-                        log.info("Switch-driver sub-handshake complete. "
-                                + "Activating switch {} with Role: MASTER",
-                                h.getSwitchInfoString());
-                        handlePendingPortStatusMessages(h); //before activation
-                        boolean success = h.controller.addActivatedMasterSwitch(
-                                h.sw.getId(), h.sw);
-                        if (!success) {
-                            disconnectDuplicate(h);
-                            return;
-                        }
-                        h.setState(MASTER);
-                    } else {
-                        log.info("Switch-driver sub-handshake complete. "
-                                + "Activating switch {} with Role: EQUAL",
-                                h.getSwitchInfoString());
-                        handlePendingPortStatusMessages(h); //before activation
-                        boolean success = h.controller.addActivatedEqualSwitch(
-                                h.sw.getId(), h.sw);
-                        if (!success) {
-                            disconnectDuplicate(h);
-                            return;
-                        }
-                        h.setState(EQUAL);
-                    }
-                } else {
-                    h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
-                }
-            }
-
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException, SwitchStateException {
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
-                    throws SwitchStateException {
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException, SwitchStateException {
-                h.pendingPortStatusMsg.add(m);
-
-            }
-        },
 
         /**
          * We are waiting for the respective switch driver to complete its
@@ -1026,39 +476,27 @@
 
             @Override
             void processOFMessage(OFChannelHandler h, OFMessage m)
-                    throws IOException {
+                    throws IOException, SwitchStateException {
                 if (m.getType() == OFType.ECHO_REQUEST) {
                     processOFEchoRequest(h, (OFEchoRequest) m);
+                } else if (m.getType() == OFType.ROLE_REPLY) {
+                    h.sw.handleRole(m);
+                } else if (m.getType() == OFType.ERROR) {
+                    if (!h.sw.handleRoleError((OFErrorMsg)m)) {
+                        h.sw.processDriverHandshakeMessage(m);
+                        if (h.sw.isDriverHandshakeComplete()) {
+                            h.setState(ACTIVE);
+                        }
+                    }
                 } else {
-                    // FIXME: other message to handle here?
-                    h.sw.processDriverHandshakeMessage(m);
-                    if (h.sw.isDriverHandshakeComplete()) {
-                        // consult the h.sw role and goto that state
-                        Role mySwitchRole = h.sw.getRole();
-                        if (mySwitchRole == Role.MASTER) {
-                            log.info("Switch-driver sub-handshake complete. "
-                                    + "Activating switch {} with Role: MASTER",
-                                    h.getSwitchInfoString());
-                            handlePendingPortStatusMessages(h); //before activation
-                            boolean success = h.controller.addActivatedMasterSwitch(
-                                    h.sw.getId(), h.sw);
-                            if (!success) {
-                                disconnectDuplicate(h);
-                                return;
-                            }
-                            h.setState(MASTER);
-                        } else {
-                            log.info("Switch-driver sub-handshake complete. "
-                                    + "Activating switch {} with Role: EQUAL",
-                                    h.getSwitchInfoString());
-                            handlePendingPortStatusMessages(h); //before activation
-                            boolean success = h.controller.addActivatedEqualSwitch(
-                                    h.sw.getId(), h.sw);
-                            if (!success) {
-                                disconnectDuplicate(h);
-                                return;
-                            }
-                            h.setState(EQUAL);
+                    if (m.getType() == OFType.EXPERIMENTER && 
+                            ((OFExperimenter) m).getExperimenter() == 
+                            RoleManager.NICIRA_EXPERIMENTER) {
+                        h.sw.handleNiciraRole(m);
+                    } else {
+                        h.sw.processDriverHandshakeMessage(m);
+                        if (h.sw.isDriverHandshakeComplete()) {
+                            h.setState(ACTIVE);
                         }
                     }
                 }
@@ -1084,7 +522,7 @@
          * if we send a role request for SLAVE /and/ receive the role reply for
          * SLAVE.
          */
-        MASTER(true) {
+        ACTIVE(true) {
             @LogMessageDoc(level = "WARN",
                     message = "Received permission error from switch {} while"
                             + "being master. Reasserting master role.",
@@ -1097,13 +535,6 @@
             @Override
             void processOFError(OFChannelHandler h, OFErrorMsg m)
                     throws IOException, SwitchStateException {
-                // first check if the error msg is in response to a role-request message
-                RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
-                if (rrstatus != RoleRecvStatus.OTHER_EXPECTATION) {
-                    // rolechanger has handled the error message - we are done
-                    return;
-                }
-
                 // if we get here, then the error message is for something else
                 if (m.getErrType() == OFErrorType.BAD_REQUEST &&
                         ((OFBadRequestErrorMsg) m).getCode() ==
@@ -1116,13 +547,10 @@
                     // 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
-                    h.counters.epermErrorWhileSwitchIsMaster.updateCounterWithFlush();
                     log.warn("Received permission error from switch {} while" +
                             "being master. Reasserting master role.",
                             h.getSwitchInfoString());
-                    //h.controller.reassertRole(h, Role.MASTER);
-                    // XXX S reassert in role changer or reconsider if all this
-                    // stuff is really needed
+                    h.sw.reassertRole();
                 } else if (m.getErrType() == OFErrorType.FLOW_MOD_FAILED &&
                         ((OFFlowModFailedErrorMsg) m).getCode() ==
                         OFFlowModFailedCode.ALL_TABLES_FULL) {
@@ -1136,35 +564,19 @@
             @Override
             void processOFStatisticsReply(OFChannelHandler h,
                     OFStatsReply m) {
-                h.sw.deliverStatisticsReply(m);
+                h.sw.handleMessage(m);
             }
 
             @Override
             void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
                     throws IOException, SwitchStateException {
-                Role role = extractNiciraRoleReply(h, m);
-                if (role == null) {
-                    // The message wasn't really a Nicira role reply. We just
-                    // dispatch it to the OFMessage listeners in this case.
-                    h.dispatchMessage(m);
-                    return;
-                }
-
-                RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(
-                        new RoleReplyInfo(role, null, m.getXid()));
-                if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-                    checkAndSetRoleTransition(h, role);
-                }
+                h.sw.handleNiciraRole(m);
             }
 
             @Override
             void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
                     throws SwitchStateException, IOException {
-                RoleReplyInfo rri = extractOFRoleReply(h, m);
-                RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
-                if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-                    checkAndSetRoleTransition(h, rri.getRole());
-                }
+                h.sw.handleRole(m);
             }
 
             @Override
@@ -1192,95 +604,6 @@
                 h.dispatchMessage(m);
             }
 
-        },
-
-        /**
-         * This controller is in EQUAL role for this switch. We enter this state
-         * after some /other/ controller instance wins mastership-role over this
-         * switch. The EQUAL role can be considered the same as the SLAVE role
-         * if this controller does NOT send commands or packets to the switch.
-         * This should always be true for OF1.0 switches. XXX S need to enforce.
-         *
-         * For OF1.3 switches, choosing this state as EQUAL instead of SLAVE,
-         * gives us the flexibility that if an app wants to send commands/packets
-         * to switches, it can, even thought it is running on a controller instance
-         * that is not in a MASTER role for this switch. Of course, it is the job
-         * of the app to ensure that commands/packets sent by this (EQUAL) controller
-         * instance does not clash/conflict with commands/packets sent by the MASTER
-         * controller for this switch. Neither the controller instances, nor the
-         * switch provides any kind of resolution mechanism should conflicts occur.
-         */
-        EQUAL(true) {
-            @Override
-            void processOFError(OFChannelHandler h, OFErrorMsg m)
-                    throws IOException, SwitchStateException {
-                // role changer will ignore the error if it isn't for it
-                RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
-                if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
-                    logError(h, m);
-                    h.dispatchMessage(m);
-                }
-            }
-
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                    OFStatsReply m) {
-                h.sw.deliverStatisticsReply(m);
-            }
-
-            @Override
-            void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
-                    throws IOException, SwitchStateException {
-                Role role = extractNiciraRoleReply(h, m);
-                // If role == null it means the message wasn't really a
-                // Nicira role reply. We ignore it in this state.
-                if (role != null) {
-                    RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(
-                            new RoleReplyInfo(role, null, m.getXid()));
-                    if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-                        checkAndSetRoleTransition(h, role);
-                    }
-                } else {
-                    unhandledMessageReceived(h, m);
-                }
-            }
-
-            @Override
-            void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
-                    throws SwitchStateException, IOException {
-                RoleReplyInfo rri = extractOFRoleReply(h, m);
-                RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
-                if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-                    checkAndSetRoleTransition(h, rri.getRole());
-                }
-            }
-
-            // XXX S needs more handlers for 1.3 switches in equal role
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException, SwitchStateException {
-                handlePortStatusMessage(h, m, true);
-            }
-
-            @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(OFChannelHandler h, OFPacketIn m) throws IOException {
-                // we don't expect packetIn while slave, reassert we are slave
-                h.counters.packetInWhileSwitchIsSlave.updateCounterNoFlush();
-                log.warn("Received PacketIn from switch {} while" +
-                        "being slave. Reasserting slave role.", h.sw);
-                //h.controller.reassertRole(h, Role.SLAVE);
-                // XXX reassert in role changer
-            }
         };
 
         private final boolean handshakeComplete;
@@ -1345,7 +668,6 @@
          */
         protected void unhandledMessageReceived(OFChannelHandler h,
                 OFMessage m) {
-            h.counters.unhandledMessage.updateCounterNoFlush();
             if (log.isDebugEnabled()) {
                 String msg = getSwitchStateMessage(h, m,
                         "Ignoring unexpected message");
@@ -1398,108 +720,7 @@
             h.channel.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.
-         * @throws SwitchStateException If the message is a Nicira role reply
-         * but the numeric role value is unknown.
-         */
-        protected Role extractNiciraRoleReply(OFChannelHandler h,
-                OFExperimenter experimenterMsg) throws SwitchStateException {
-            int vendor = (int) experimenterMsg.getExperimenter();
-            if (vendor != 0x2320) {
-                return null;
-            }
-            OFNiciraControllerRoleReply nrr =
-                    (OFNiciraControllerRoleReply) experimenterMsg;
 
-            Role role = null;
-            OFNiciraControllerRole ncr = nrr.getRole();
-            switch(ncr) {
-            case ROLE_MASTER:
-                role = Role.MASTER;
-                break;
-            case ROLE_OTHER:
-                role = Role.EQUAL;
-                break;
-            case ROLE_SLAVE:
-                role = Role.SLAVE;
-                break;
-            default: //handled below
-            }
-
-            if (role == null) {
-                String msg = String.format("Switch: [%s], State: [%s], "
-                        + "received NX_ROLE_REPLY with invalid role "
-                        + "value %s",
-                        h.getSwitchInfoString(),
-                        this.toString(),
-                        nrr.getRole());
-                throw new SwitchStateException(msg);
-            }
-            return role;
-        }
-
-        /**
-         * Helper class returns role reply information in the format understood
-         * by the controller.
-         */
-        protected static class RoleReplyInfo {
-            private Role role;
-            private U64 genId;
-            private long xid;
-
-            RoleReplyInfo(Role role, U64 genId, long xid) {
-                this.role = role;
-                this.genId = genId;
-                this.xid = xid;
-            }
-            public Role getRole() { return role; }
-            public U64 getGenId() { return genId; }
-            public long getXid() { return xid; }
-            @Override
-            public String toString() {
-                return "[Role:" + role + " GenId:" + genId + " Xid:" + xid + "]";
-            }
-        }
-
-        /**
-         * Extract the role information from an OF1.3 Role Reply Message.
-         * @param h
-         * @param rrmsg
-         * @return RoleReplyInfo object
-         * @throws SwitchStateException
-         */
-        protected RoleReplyInfo extractOFRoleReply(OFChannelHandler h,
-                OFRoleReply rrmsg) throws SwitchStateException {
-            OFControllerRole cr = rrmsg.getRole();
-            Role role = null;
-            switch(cr) {
-            case ROLE_EQUAL:
-                role = Role.EQUAL;
-                break;
-            case ROLE_MASTER:
-                role = Role.MASTER;
-                break;
-            case ROLE_SLAVE:
-                role = Role.SLAVE;
-                break;
-            case ROLE_NOCHANGE: // switch should send current role
-            default:
-                String msg = String.format("Unknown controller role %s "
-                        + "received from switch %s", cr, h.sw);
-                throw new SwitchStateException(msg);
-            }
-
-            return new RoleReplyInfo(role, rrmsg.getGenerationId(), rrmsg.getXid());
-        }
 
         /**
          * Handles all pending port status messages before a switch is declared
@@ -1567,52 +788,9 @@
                 throw new SwitchStateException(msg);
             }
 
-            Collection<PortChangeEvent> changes = h.sw.processOFPortStatus(m);
-            if (doNotify) {
-                for (PortChangeEvent ev: changes) {
-                    h.controller.notifyPortChanged(h.sw.getId(), ev.port, ev.type);
-                }
-            }
+            h.sw.handleMessage(m);
         }
 
-        /**
-         * Checks if the role received (from the role-reply msg) is different
-         * from the existing role in the IOFSwitch object for this controller.
-         * If so, it transitions the controller to the new role. Note that
-         * the caller should have already verified that the role-reply msg
-         * received was in response to a role-request msg sent out by this
-         * controller after hearing from the registry service.
-         *
-         * @param h the ChannelHandler that received the message
-         * @param role the role in the recieved role reply message
-         */
-        protected void checkAndSetRoleTransition(OFChannelHandler h, Role role) {
-            // we received a role-reply in response to a role message
-            // sent after hearing from the registry service. It is
-            // possible that the role of this controller instance for
-            // this switch has changed:
-            // for 1.0 switch: from MASTER to SLAVE
-            // for 1.3 switch: from MASTER to EQUAL
-            if ((h.sw.getRole() == Role.MASTER && role == Role.SLAVE) ||
-                    (h.sw.getRole() == Role.MASTER && role == Role.EQUAL)) {
-                // the mastership has changed
-                h.sw.setRole(role);
-                h.setState(EQUAL);
-                h.controller.transitionToEqualSwitch(h.sw.getId());
-                return;
-            }
-
-            // or for both 1.0 and 1.3 switches from EQUAL to MASTER.
-            // note that for 1.0, even though we mean SLAVE,
-            // internally we call the role EQUAL.
-            if (h.sw.getRole() == Role.EQUAL && role == Role.MASTER) {
-                // the mastership has changed
-                h.sw.setRole(role);
-                h.setState(MASTER);
-                h.controller.transitionToMasterSwitch(h.sw.getId());
-                return;
-            }
-        }
 
         /**
          * Process an OF message received on the channel and
@@ -1635,7 +813,6 @@
          */
         void processOFMessage(OFChannelHandler h, OFMessage m)
                 throws IOException, SwitchStateException {
-            h.roleChanger.checkTimeout();
             switch(m.getType()) {
             case HELLO:
                 processOFHello(h, (OFHello) m);
@@ -1812,10 +989,6 @@
             unhandledMessageReceived(h, m);
         }
 
-        void handleUnsentRoleMessage(OFChannelHandler h, Role role,
-                RoleRecvStatus expectation) throws IOException {
-            // do nothing in most states
-        }
     }
 
 
@@ -1830,7 +1003,6 @@
             + "specified IP address")
     public void channelConnected(ChannelHandlerContext ctx,
             ChannelStateEvent e) throws Exception {
-        counters.switchConnected.updateCounterWithFlush();
         channel = e.getChannel();
         log.info("New switch connection from {}",
                 channel.getRemoteAddress());
@@ -1853,7 +1025,7 @@
                 // switch was a duplicate-dpid, calling the method below would clear
                 // all state for the original switch (with the same dpid),
                 // which we obviously don't want.
-                controller.removeConnectedSwitch(thisdpid);
+                sw.removeConnectedSwitch();
             } else {
                 // A duplicate was disconnected on this ChannelHandler,
                 // this is the same switch reconnecting, but the original state was
@@ -1914,12 +1086,10 @@
             // switch timeout
             log.error("Disconnecting switch {} due to read timeout",
                     getSwitchInfoString());
-            counters.switchDisconnectReadTimeout.updateCounterWithFlush();
             ctx.getChannel().close();
         } else if (e.getCause() instanceof HandshakeTimeoutException) {
             log.error("Disconnecting switch {}: failed to complete handshake",
                     getSwitchInfoString());
-            counters.switchDisconnectHandshakeTimeout.updateCounterWithFlush();
             ctx.getChannel().close();
         } else if (e.getCause() instanceof ClosedChannelException) {
             log.debug("Channel for sw {} already closed", getSwitchInfoString());
@@ -1930,7 +1100,6 @@
                 // still print stack trace if debug is enabled
                 log.debug("StackTrace for previous Exception: ", e.getCause());
             }
-            counters.switchDisconnectIOError.updateCounterWithFlush();
             ctx.getChannel().close();
         } else if (e.getCause() instanceof SwitchStateException) {
             log.error("Disconnecting switch {} due to switch state error: {}",
@@ -1939,23 +1108,19 @@
                 // still print stack trace if debug is enabled
                 log.debug("StackTrace for previous Exception: ", e.getCause());
             }
-            counters.switchDisconnectSwitchStateException.updateCounterWithFlush();
             ctx.getChannel().close();
         } else if (e.getCause() instanceof OFParseError) {
             log.error("Disconnecting switch "
                     + getSwitchInfoString() +
                     " due to message parse failure",
                     e.getCause());
-            counters.switchDisconnectParseError.updateCounterWithFlush();
             ctx.getChannel().close();
         } else if (e.getCause() instanceof RejectedExecutionException) {
             log.warn("Could not process message: queue full");
-            counters.rejectedExecutionException.updateCounterWithFlush();
         } else {
             log.error("Error while processing message from switch "
                     + getSwitchInfoString()
                     + "state " + this.state, e.getCause());
-            counters.switchDisconnectOtherException.updateCounterWithFlush();
             ctx.getChannel().close();
         }
     }
@@ -1986,12 +1151,10 @@
 
 
             for (OFMessage ofm : msglist) {
-                counters.messageReceived.updateCounterNoFlush();
                 // Do the actual packet processing
                 state.processOFMessage(this, ofm);
             }
         } else {
-            counters.messageReceived.updateCounterNoFlush();
             state.processOFMessage(this, (OFMessage) e.getMessage());
         }
     }
@@ -2080,7 +1243,7 @@
         channel.write(Collections.singletonList(m));
     }
 
-    private void setSwitchRole(Role role) {
+    private void setSwitchRole(RoleState role) {
         sw.setRole(role);
     }
 
@@ -2146,9 +1309,4 @@
         return state;
     }
 
-    void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) {
-        roleChanger = new RoleChanger(roleTimeoutMs);
-    }
-
-
 }
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
new file mode 100644
index 0000000..976e347
--- /dev/null
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
@@ -0,0 +1,263 @@
+package org.onlab.onos.of.controller.impl.internal;
+
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.of.controller.Dpid;
+import org.onlab.onos.of.controller.OpenFlowController;
+import org.onlab.onos.of.controller.OpenFlowSwitch;
+import org.onlab.onos.of.controller.OpenFlowSwitchListener;
+import org.onlab.onos.of.controller.PacketListener;
+import org.onlab.onos.of.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(immediate = true)
+@Service
+public class OpenFlowControllerImpl implements OpenFlowController {
+
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches;
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches;
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches;
+
+    protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
+    protected ArrayList<OpenFlowSwitchListener> ofEventListener;
+
+    private final Controller ctrl = new Controller();
+
+    @Activate
+    public void activate() {
+        ctrl.start(agent);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        ctrl.stop();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getSwitches() {
+        return connectedSwitches.values();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getMasterSwitches() {
+        return activeMasterSwitches.values();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getEqualSwitches() {
+        return activeEqualSwitches.values();
+    }
+
+    @Override
+    public OpenFlowSwitch getSwitch(Dpid dpid) {
+        return connectedSwitches.get(dpid.value());
+    }
+
+    @Override
+    public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
+        return activeMasterSwitches.get(dpid.value());
+    }
+
+    @Override
+    public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
+        return activeEqualSwitches.get(dpid.value());    }
+
+    @Override
+    public void addListener(OpenFlowSwitchListener listener) {
+        if (!ofEventListener.contains(listener)) {
+            this.ofEventListener.add(listener);
+        }
+    }
+
+    @Override
+    public void removeListener(OpenFlowSwitchListener listener) {
+        this.ofEventListener.remove(listener);
+    }
+
+    @Override
+    public void addPacketListener(int priority, PacketListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removePacketListener(PacketListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void write(Dpid dpid, OFMessage msg) {
+        this.getSwitch(dpid).write(msg);
+    }
+
+    @Override
+    public void processPacket(OFMessage msg) {
+    }
+
+    @Override
+    public void setRole(Dpid dpid, RoleState role) {
+        switch (role) {
+        case MASTER:
+            agent.transitionToMasterSwitch(dpid.value());
+            break;
+        case EQUAL:
+            agent.transitionToEqualSwitch(dpid.value());
+            break;
+        case SLAVE:
+            //agent.transitionToSlaveSwitch(dpid.value());
+            break;
+        default:
+            //WTF role is this?
+        }
+
+    }
+
+    public class OpenFlowSwitchAgent {
+
+        private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
+        private Lock switchLock = new ReentrantLock();
+
+        public boolean addConnectedSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+            if (connectedSwitches.get(dpid) != null) {
+                log.error("Trying to add connectedSwitch but found a previous "
+                        + "value for dpid: {}", dpid);
+                return false;
+            } else {
+                log.error("Added switch {}", dpid);
+                connectedSwitches.put(dpid, sw);
+                for (OpenFlowSwitchListener l : ofEventListener) {
+                    l.switchAdded(new Dpid(dpid));
+                }
+                return true;
+            }
+        }
+
+        private boolean validActivation(long dpid) {
+            if (connectedSwitches.get(dpid) == null) {
+                log.error("Trying to activate switch but is not in "
+                        + "connected switches: dpid {}. Aborting ..",
+                        HexString.toHexString(dpid));
+                return false;
+            }
+            if (activeMasterSwitches.get(dpid) != null ||
+                    activeEqualSwitches.get(dpid) != null) {
+                log.error("Trying to activate switch but it is already "
+                        + "activated: dpid {}. Found in activeMaster: {} "
+                        + "Found in activeEqual: {}. Aborting ..", new Object[] {
+                                HexString.toHexString(dpid),
+                                (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
+                                (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
+                return false;
+            }
+            return true;
+        }
+
+        /**
+         * Called when a switch is activated, with this controller's role as MASTER.
+         */
+        protected boolean addActivatedMasterSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+            switchLock.lock();
+            try {
+                if (!validActivation(dpid)) {
+                    return false;
+                }
+                activeMasterSwitches.put(dpid, sw);
+                return true;
+            } finally {
+                switchLock.unlock();
+            }
+    }
+
+        /**
+         * Called when a switch is activated, with this controller's role as EQUAL.
+         */
+        protected boolean addActivatedEqualSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+            switchLock.lock();
+            try {
+                    if (!validActivation(dpid)) {
+                        return false;
+                    }
+                    activeEqualSwitches.put(dpid, sw);
+                    return true;
+            } finally {
+                switchLock.unlock();
+            }
+        }
+
+        /**
+         * Called when this controller's role for a switch transitions from equal
+         * to master. For 1.0 switches, we internally refer to the role 'slave' as
+         * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
+         */
+        protected void transitionToMasterSwitch(long dpid) {
+            switchLock.lock();
+            try {
+                OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
+                if (sw == null) {
+                    log.error("Transition to master called on sw {}, but switch "
+                            + "was not found in controller-cache", dpid);
+                    return;
+                }
+                activeMasterSwitches.put(dpid, sw);
+            } finally {
+                switchLock.unlock();
+            }
+        }
+
+
+        /**
+         * Called when this controller's role for a switch transitions to equal.
+         * For 1.0 switches, we internally refer to the role 'slave' as
+         * 'equal'.
+         */
+        protected void transitionToEqualSwitch(long dpid) {
+            switchLock.lock();
+            try {
+                OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
+                if (sw == null) {
+                    log.error("Transition to equal called on sw {}, but switch "
+                            + "was not found in controller-cache", dpid);
+                    return;
+                }
+                activeEqualSwitches.put(dpid, sw);
+            } finally {
+                switchLock.unlock();
+            }
+
+        }
+
+        /**
+         * Clear all state in controller switch maps for a switch that has
+         * disconnected from the local controller. Also release control for
+         * that switch from the global repository. Notify switch listeners.
+         */
+        public void removeConnectedSwitch(long dpid) {
+            connectedSwitches.remove(dpid);
+            OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
+            if (sw == null) {
+                sw = activeEqualSwitches.remove(dpid);
+            }
+            for (OpenFlowSwitchListener l : ofEventListener) {
+                l.switchRemoved(new Dpid(dpid));
+            }
+        }
+
+        public void processMessage(OFMessage m) {
+            processPacket(m);
+        }
+    }
+
+
+
+}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
new file mode 100644
index 0000000..f31487a
--- /dev/null
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/RoleManager.java
@@ -0,0 +1,708 @@
+package org.onlab.onos.of.controller.impl.internal;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.onlab.onos.of.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFErrorType;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply;
+import org.projectfloodlight.openflow.protocol.OFRoleReply;
+import org.projectfloodlight.openflow.protocol.OFRoleRequest;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
+import org.projectfloodlight.openflow.protocol.errormsg.OFRoleRequestFailedErrorMsg;
+import org.projectfloodlight.openflow.types.U64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 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.
+ */
+class RoleManager {
+    protected static final long NICIRA_EXPERIMENTER = 0x2320;
+
+    private static Logger log = LoggerFactory.getLogger(RoleManager.class);
+    // 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 int pendingXid;
+    // the role that's pending
+    private RoleState pendingRole;
+
+    // the expectation set by the caller for the returned role
+    private RoleRecvStatus expectation;
+    private AtomicInteger xidCounter;
+    private AbstractOpenFlowSwitch sw;
+
+
+    public RoleManager(AbstractOpenFlowSwitch sw) {
+        this.requestPending = false;
+        this.pendingXid = -1;
+        this.pendingRole = null;
+        this.xidCounter = new AtomicInteger(0);
+        this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE;
+        this.sw = sw;
+    }
+
+    /**
+     * Send NX role request message to the switch requesting the specified
+     * role.
+     *
+     * @param sw switch to send the role request message to
+     * @param role role to request
+     */
+    private int sendNxRoleRequest(RoleState role) throws IOException {
+        // Convert the role enum to the appropriate role to send
+        OFNiciraControllerRole roleToSend = OFNiciraControllerRole.ROLE_OTHER;
+        switch (role) {
+        case MASTER:
+            roleToSend = OFNiciraControllerRole.ROLE_MASTER;
+            break;
+        case SLAVE:
+        case EQUAL:
+        default:
+            // ensuring that the only two roles sent to 1.0 switches with
+            // Nicira role support, are MASTER and SLAVE
+            roleToSend = OFNiciraControllerRole.ROLE_SLAVE;
+            log.warn("Sending Nx Role.SLAVE to switch {}.", sw);
+        }
+        int xid = xidCounter.getAndIncrement();
+        OFExperimenter roleRequest = OFFactories.getFactory(OFVersion.OF_10)
+                .buildNiciraControllerRoleRequest()
+                .setXid(xid)
+                .setRole(roleToSend)
+                .build();
+        sw.write(Collections.<OFMessage>singletonList(roleRequest));
+        return xid;
+    }
+
+    private int sendOF13RoleRequest(RoleState role) throws IOException {
+        // Convert the role enum to the appropriate role to send
+        OFControllerRole roleToSend = OFControllerRole.ROLE_NOCHANGE;
+        switch (role) {
+        case EQUAL:
+            roleToSend = OFControllerRole.ROLE_EQUAL;
+            break;
+        case MASTER:
+            roleToSend = OFControllerRole.ROLE_MASTER;
+            break;
+        case SLAVE:
+            roleToSend = OFControllerRole.ROLE_SLAVE;
+            break;
+        default:
+            log.warn("Sending default role.noChange to switch {}."
+                    + " Should only be used for queries.", sw);
+        }
+
+        int xid = xidCounter.getAndIncrement();
+        OFRoleRequest rrm = OFFactories.getFactory(OFVersion.OF_13)
+                .buildRoleRequest()
+                .setRole(roleToSend)
+                .setXid(xid)
+                //FIXME fix below when we actually use generation ids
+                .setGenerationId(U64.ZERO)
+                .build();
+        sw.write(rrm);
+        return xid;
+    }
+
+    /**
+     * Send a role request with the given role to the switch and update
+     * the pending request and timestamp.
+     * Sends an OFPT_ROLE_REQUEST to an OF1.3 switch, OR
+     * Sends an NX_ROLE_REQUEST to an OF1.0 switch if configured to support it
+     * in the IOFSwitch driver. If not supported, this method sends nothing
+     * and returns 'false'. The caller should take appropriate action.
+     *
+     * One other optimization we do here is that for OF1.0 switches with
+     * Nicira role message support, we force the Role.EQUAL to become
+     * Role.SLAVE, as there is no defined behavior for the Nicira role OTHER.
+     * We cannot expect it to behave like SLAVE. We don't have this problem with
+     * OF1.3 switches, because Role.EQUAL is well defined and we can simulate
+     * SLAVE behavior by using ASYNC messages.
+     *
+     * @param role
+     * @throws IOException
+     * @returns false if and only if the switch does not support role-request
+     * messages, according to the switch driver; true otherwise.
+     */
+    synchronized boolean sendRoleRequest(RoleState role, RoleRecvStatus exp)
+            throws IOException {
+        this.expectation = exp;
+
+        if (sw.factory().getVersion() == OFVersion.OF_10) {
+            Boolean supportsNxRole = (Boolean)
+                    sw.supportNxRole();
+            if (!supportsNxRole) {
+                log.debug("Switch driver indicates no support for Nicira "
+                        + "role request messages. Not sending ...");
+                handleUnsentRoleMessage(role,
+                        expectation);
+                return false;
+            }
+            // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn.
+            // make Role.EQUAL become Role.SLAVE
+            role = (role == RoleState.EQUAL) ? RoleState.SLAVE : role;
+            pendingXid = sendNxRoleRequest(role);
+            pendingRole = role;
+            requestPending = true;
+        } else {
+            // OF1.3 switch, use OFPT_ROLE_REQUEST message
+            pendingXid = sendOF13RoleRequest(role);
+            pendingRole = role;
+            requestPending = true;
+        }
+        return true;
+    }
+
+    private void handleUnsentRoleMessage(RoleState role,
+            RoleRecvStatus exp) throws IOException {
+        // typically this is triggered for a switch where role messages
+        // are not supported - we confirm that the role being set is
+        // master
+        if (exp != RoleRecvStatus.MATCHED_SET_ROLE) {
+
+            log.error("Expected MASTER role from registry for switch "
+                    + "which has no support for role-messages."
+                    + "Received {}. It is possible that this switch "
+                    + "is connected to other controllers, in which "
+                    + "case it should support role messages - not "
+                    + "moving forward.", role);
+
+        }
+
+    }
+
+    /**
+     * Deliver a received role reply.
+     *
+     * 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, and
+     * return
+     *
+     * If no request is pending we disconnect with a SwitchStateException
+     *
+     * @param RoleReplyInfo information about role-reply in format that
+     *                      controller can understand.
+     * @throws SwitchStateException if no request is pending
+     */
+    synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
+            throws SwitchStateException {
+        if (!requestPending) {
+            RoleState currentRole = (sw != null) ? sw.getRole() : null;
+            if (currentRole != null) {
+                if (currentRole == rri.getRole()) {
+                    // Don't disconnect if the role reply we received is
+                    // for the same role we are already in.
+                    log.debug("Received unexpected RoleReply from "
+                            + "Switch: {}. "
+                            + "Role in reply is same as current role of this "
+                            + "controller for this sw. Ignoring ...",
+                            sw.getStringId());
+                    return RoleRecvStatus.OTHER_EXPECTATION;
+                } else {
+                    String msg = String.format("Switch: [%s], "
+                            + "received unexpected RoleReply[%s]. "
+                            + "No roles are pending, and this controller's "
+                            + "current role:[%s] does not match reply. "
+                            + "Disconnecting switch ... ",
+                            sw.getStringId(),
+                            rri, currentRole);
+                    throw new SwitchStateException(msg);
+                }
+            }
+            log.debug("Received unexpected RoleReply {} from "
+                    + "Switch: {}. "
+                    + "This controller has no current role for this sw. "
+                    + "Ignoring ...", new Object[] {rri,
+                            sw.getStringId(), });
+            return RoleRecvStatus.OTHER_EXPECTATION;
+        }
+
+        int xid = (int) rri.getXid();
+        RoleState role = rri.getRole();
+        // XXX S should check generation id meaningfully and other cases of expectations
+        // U64 genId = rri.getGenId();
+
+        if (pendingXid != xid) {
+            log.debug("Received older role reply from " +
+                    "switch {} ({}). Ignoring. " +
+                    "Waiting for {}, xid={}",
+                    new Object[] {sw.getStringId(), rri,
+                    pendingRole, pendingXid });
+            return RoleRecvStatus.OLD_REPLY;
+        }
+
+        if (pendingRole == role) {
+            log.debug("Received role reply message from {} that matched "
+                    + "expected role-reply {} with expectations {}",
+                    new Object[] {sw.getStringId(), role, expectation});
+
+            //setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY); dont want to set state here
+            if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE ||
+                    expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
+                return expectation;
+            } else {
+                return RoleRecvStatus.OTHER_EXPECTATION;
+            }
+        }
+
+        // if xids match but role's don't, perhaps its a query (OF1.3)
+        if (expectation == RoleRecvStatus.REPLY_QUERY) {
+            return expectation;
+        }
+
+        return RoleRecvStatus.OTHER_EXPECTATION;
+    }
+
+    /**
+     * Called if we receive an  error message. If the xid matches the
+     * pending request we handle it otherwise we ignore it.
+     *
+     * 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
+     */
+    synchronized RoleRecvStatus deliverError(OFErrorMsg error)
+            throws SwitchStateException {
+        if (!requestPending) {
+            log.debug("Received an error msg from sw {}, but no pending "
+                    + "requests in role-changer; not handling ...",
+                   sw.getStringId());
+            return RoleRecvStatus.OTHER_EXPECTATION;
+        }
+        if (pendingXid != error.getXid()) {
+            if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
+                log.debug("Received an error msg from sw {} for a role request,"
+                        + " but not for pending request in role-changer; "
+                        + " ignoring error {} ...",
+                        sw.getStringId(), error);
+            }
+            return RoleRecvStatus.OTHER_EXPECTATION;
+        }
+        // it is an error related to a currently pending role request message
+        if (error.getErrType() == OFErrorType.BAD_REQUEST) {
+            log.error("Received a error msg {} from sw {} for "
+                    + "pending role request {}. Switch driver indicates "
+                    + "role-messaging is supported. Possible issues in "
+                    + "switch driver configuration?", new Object[] {
+                            ((OFBadRequestErrorMsg) error).toString(),
+                            sw.getStringId(), pendingRole
+                    });
+            return RoleRecvStatus.UNSUPPORTED;
+        }
+
+        if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
+            OFRoleRequestFailedErrorMsg rrerr =
+                    (OFRoleRequestFailedErrorMsg) error;
+            switch (rrerr.getCode()) {
+            case BAD_ROLE:
+                // switch says that current-role-req has bad role?
+                // for now we disconnect
+                // fall-thru
+            case STALE:
+                // switch says that current-role-req has stale gen-id?
+                // for now we disconnect
+                // fall-thru
+            case UNSUP:
+                // switch says that current-role-req has role that
+                // cannot be supported? for now we disconnect
+                String msgx = String.format("Switch: [%s], "
+                        + "received Error to for pending role request [%s]. "
+                        + "Error:[%s]. Disconnecting switch ... ",
+                        sw.getStringId(),
+                        pendingRole, rrerr);
+                throw new SwitchStateException(msgx);
+            default:
+                break;
+            }
+        }
+
+        // This error message was for a role request message but we dont know
+        // how to handle errors for nicira role request messages
+        return RoleRecvStatus.OTHER_EXPECTATION;
+    }
+
+    /**
+     * 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.
+     * @throws SwitchStateException If the message is a Nicira role reply
+     * but the numeric role value is unknown.
+     */
+    protected RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg)
+            throws SwitchStateException {
+        int vendor = (int) experimenterMsg.getExperimenter();
+        if (vendor != 0x2320) {
+            return null;
+        }
+        OFNiciraControllerRoleReply nrr =
+                (OFNiciraControllerRoleReply) experimenterMsg;
+
+        RoleState role = null;
+        OFNiciraControllerRole ncr = nrr.getRole();
+        switch(ncr) {
+        case ROLE_MASTER:
+            role = RoleState.MASTER;
+            break;
+        case ROLE_OTHER:
+            role = RoleState.EQUAL;
+            break;
+        case ROLE_SLAVE:
+            role = RoleState.SLAVE;
+            break;
+        default: //handled below
+        }
+
+        if (role == null) {
+            String msg = String.format("Switch: [%s], "
+                    + "received NX_ROLE_REPLY with invalid role "
+                    + "value %s",
+                    sw.getStringId(),
+                    nrr.getRole());
+            throw new SwitchStateException(msg);
+        }
+        return role;
+    }
+
+    /**
+     * When we remove a pending role request we use this enum to indicate how we
+     * arrived at the decision. When we send a role request to the switch, we
+     * also use  this enum to indicate what we expect back from the switch, so the
+     * role changer can match the reply to our expectation.
+     */
+    public enum RoleRecvStatus {
+        /** The switch returned an error indicating that roles are not.
+         * supported*/
+        UNSUPPORTED,
+        /** The request timed out. */
+        NO_REPLY,
+        /** The reply was old, there is a newer request pending. */
+        OLD_REPLY,
+        /**
+         *  The reply's role matched the role that this controller set in the
+         *  request message - invoked either initially at startup or to reassert
+         *  current role.
+         */
+        MATCHED_CURRENT_ROLE,
+        /**
+         *  The reply's role matched the role that this controller set in the
+         *  request message - this is the result of a callback from the
+         *  global registry, followed by a role request sent to the switch.
+         */
+        MATCHED_SET_ROLE,
+        /**
+         * The reply's role was a response to the query made by this controller.
+         */
+        REPLY_QUERY,
+        /** We received a role reply message from the switch
+         *  but the expectation was unclear, or there was no expectation.
+         */
+        OTHER_EXPECTATION,
+    }
+
+    /**
+     * Helper class returns role reply information in the format understood
+     * by the controller.
+     */
+    protected static class RoleReplyInfo {
+        private RoleState role;
+        private U64 genId;
+        private long xid;
+
+        RoleReplyInfo(RoleState role, U64 genId, long xid) {
+            this.role = role;
+            this.genId = genId;
+            this.xid = xid;
+        }
+        public RoleState getRole() { return role; }
+        public U64 getGenId() { return genId; }
+        public long getXid() { return xid; }
+        @Override
+        public String toString() {
+            return "[Role:" + role + " GenId:" + genId + " Xid:" + xid + "]";
+        }
+    }
+
+    /**
+     * Extract the role information from an OF1.3 Role Reply Message.
+     * @param h
+     * @param rrmsg
+     * @return RoleReplyInfo object
+     * @throws SwitchStateException
+     */
+    protected RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg)
+            throws SwitchStateException {
+        OFControllerRole cr = rrmsg.getRole();
+        RoleState role = null;
+        switch(cr) {
+        case ROLE_EQUAL:
+            role = RoleState.EQUAL;
+            break;
+        case ROLE_MASTER:
+            role = RoleState.MASTER;
+            break;
+        case ROLE_SLAVE:
+            role = RoleState.SLAVE;
+            break;
+        case ROLE_NOCHANGE: // switch should send current role
+        default:
+            String msg = String.format("Unknown controller role %s "
+                    + "received from switch %s", cr, sw);
+            throw new SwitchStateException(msg);
+        }
+
+        return new RoleReplyInfo(role, rrmsg.getGenerationId(), rrmsg.getXid());
+    }
+
+}
+
+
+///**
+// * We are waiting for a role reply message in response to a role request
+// * sent after hearing back from the registry service -- OR -- we are
+// * just waiting to hear back from the registry service in the case that
+// * the switch does not support role messages. If completed successfully,
+// * the controller's role for this switch will be set here.
+// * Before we move to the state corresponding to the role, we allow the
+// * switch specific driver to complete its configuration. This configuration
+// * typically depends on the role the controller is playing for this switch.
+// * And so we set the switch role (for 'this' controller) before we start
+// * the driver-sub-handshake.
+// * Next State: WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
+// */
+//WAIT_INITIAL_ROLE(false) {
+//    @Override
+//    void processOFError(OFChannelHandler h, OFErrorMsg m)
+//            throws SwitchStateException {
+//        // role changer will ignore the error if it isn't for it
+//        RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
+//        if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
+//            logError(h, m);
+//        }
+//    }
+//
+//    @Override
+//    void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
+//            throws IOException, SwitchStateException {
+//        Role role = extractNiciraRoleReply(h, m);
+//        // If role == null it means the vendor (experimenter) message
+//        // wasn't really a Nicira role reply. We ignore this case.
+//        if (role != null) {
+//            RoleReplyInfo rri = new RoleReplyInfo(role, null, m.getXid());
+//            RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
+//            if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+//                setRoleAndStartDriverHandshake(h, rri.getRole());
+//            } // else do nothing - wait for the correct expected reply
+//        } else {
+//            unhandledMessageReceived(h, m);
+//        }
+//    }
+//
+//    @Override
+//    void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
+//            throws SwitchStateException, IOException {
+//        RoleReplyInfo rri = extractOFRoleReply(h, m);
+//        RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
+//        if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+//            setRoleAndStartDriverHandshake(h, rri.getRole());
+//        } // else do nothing - wait for the correct expected reply
+//    }
+//
+//    @Override
+//    void handleUnsentRoleMessage(OFChannelHandler h, Role role,
+//            RoleRecvStatus expectation) throws IOException {
+//        // typically this is triggered for a switch where role messages
+//        // are not supported - we confirm that the role being set is
+//        // master and move to the next state
+//        if (expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
+//            if (role == Role.MASTER) {
+//                setRoleAndStartDriverHandshake(h, role);
+//            } else {
+//                log.error("Expected MASTER role from registry for switch "
+//                        + "which has no support for role-messages."
+//                        + "Received {}. It is possible that this switch "
+//                        + "is connected to other controllers, in which "
+//                        + "case it should support role messages - not "
+//                        + "moving forward.", role);
+//            }
+//        } // else do nothing - wait to hear back from registry
+//
+//    }
+//
+//    private void setRoleAndStartDriverHandshake(OFChannelHandler h,
+//            Role role) throws IOException {
+//        h.setSwitchRole(role);
+//        h.sw.startDriverHandshake();
+//        if (h.sw.isDriverHandshakeComplete()) {
+//            Role mySwitchRole = h.sw.getRole();
+//            if (mySwitchRole == Role.MASTER) {
+//                log.info("Switch-driver sub-handshake complete. "
+//                        + "Activating switch {} with Role: MASTER",
+//                        h.sw.getStringId());
+//                handlePendingPortStatusMessages(h); //before activation
+//                boolean success = h.sw.addActivatedMasterSwitch();
+//                if (!success) {
+//                    disconnectDuplicate(h);
+//                    return;
+//                }
+//                h.setState(MASTER);
+//            } else {
+//                log.info("Switch-driver sub-handshake complete. "
+//                        + "Activating switch {} with Role: EQUAL",
+//                        h.sw.getStringId());
+//                handlePendingPortStatusMessages(h); //before activation
+//                boolean success = h.sw.addActivatedEqualSwitch();
+//                if (!success) {
+//                    disconnectDuplicate(h);
+//                    return;
+//                }
+//                h.setState(EQUAL);
+//            }
+//        } else {
+//            h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
+//        }
+//    }
+//
+//    @Override
+//    void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
+//            throws IOException, SwitchStateException {
+//        illegalMessageReceived(h, m);
+//    }
+//
+//    @Override
+//    void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
+//            throws SwitchStateException {
+//        illegalMessageReceived(h, m);
+//    }
+//
+//    @Override
+//    void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+//            throws IOException, SwitchStateException {
+//        h.pendingPortStatusMsg.add(m);
+//
+//    }
+//},
+
+
+
+
+
+
+
+///**
+// * This controller is in EQUAL role for this switch. We enter this state
+// * after some /other/ controller instance wins mastership-role over this
+// * switch. The EQUAL role can be considered the same as the SLAVE role
+// * if this controller does NOT send commands or packets to the switch.
+// * This should always be true for OF1.0 switches. XXX S need to enforce.
+// *
+// * For OF1.3 switches, choosing this state as EQUAL instead of SLAVE,
+// * gives us the flexibility that if an app wants to send commands/packets
+// * to switches, it can, even thought it is running on a controller instance
+// * that is not in a MASTER role for this switch. Of course, it is the job
+// * of the app to ensure that commands/packets sent by this (EQUAL) controller
+// * instance does not clash/conflict with commands/packets sent by the MASTER
+// * controller for this switch. Neither the controller instances, nor the
+// * switch provides any kind of resolution mechanism should conflicts occur.
+// */
+//EQUAL(true) {
+//    @Override
+//    void processOFError(OFChannelHandler h, OFErrorMsg m)
+//            throws IOException, SwitchStateException {
+//        // role changer will ignore the error if it isn't for it
+//        RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
+//        if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
+//            logError(h, m);
+//            h.dispatchMessage(m);
+//        }
+//    }
+//
+//    @Override
+//    void processOFStatisticsReply(OFChannelHandler h,
+//            OFStatsReply m) {
+//        h.sw.handleMessage(m);
+//    }
+//
+//    @Override
+//    void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
+//            throws IOException, SwitchStateException {
+//        Role role = extractNiciraRoleReply(h, m);
+//        // If role == null it means the message wasn't really a
+//        // Nicira role reply. We ignore it in this state.
+//        if (role != null) {
+//            RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(
+//                    new RoleReplyInfo(role, null, m.getXid()));
+//            if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+//                checkAndSetRoleTransition(h, role);
+//            }
+//        } else {
+//            unhandledMessageReceived(h, m);
+//        }
+//    }
+//
+//    @Override
+//    void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
+//            throws SwitchStateException, IOException {
+//        RoleReplyInfo rri = extractOFRoleReply(h, m);
+//        RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
+//        if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+//            checkAndSetRoleTransition(h, rri.getRole());
+//        }
+//    }
+//
+//    // XXX S needs more handlers for 1.3 switches in equal role
+//
+//    @Override
+//    void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+//            throws IOException, SwitchStateException {
+//        handlePortStatusMessage(h, m, true);
+//    }
+//
+//    @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(OFChannelHandler h, OFPacketIn m) throws IOException {
+//        // we don't expect packetIn while slave, reassert we are slave
+//        h.counters.packetInWhileSwitchIsSlave.updateCounterNoFlush();
+//        log.warn("Received PacketIn from switch {} while" +
+//                "being slave. Reasserting slave role.", h.sw);
+//        //h.controller.reassertRole(h, Role.SLAVE);
+//        // XXX reassert in role changer
+//    }
+//};
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/ControllerRegistryEntry.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/ControllerRegistryEntry.java
deleted file mode 100644
index 5e83348..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/ControllerRegistryEntry.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.onlab.onos.of.controller.impl.registry;
-
-
-
-public class ControllerRegistryEntry implements Comparable<ControllerRegistryEntry> {
-    //
-    // TODO: Refactor the implementation and decide whether controllerId
-    // is needed. If "yes", we might need to consider it inside the
-    // compareTo(), equals() and hashCode() implementations.
-    //
-    private final String controllerId;
-    private final int sequenceNumber;
-
-    public ControllerRegistryEntry(String controllerId, int sequenceNumber) {
-        this.controllerId = controllerId;
-        this.sequenceNumber = sequenceNumber;
-    }
-
-    public String getControllerId() {
-        return controllerId;
-    }
-
-    /**
-     * Compares this object with the specified object for order.
-     * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
-     * and doesn't include the controllerId.
-     *
-     * @param o the object to be compared.
-     * @return a negative integer, zero, or a positive integer as this object
-     * is less than, equal to, or greater than the specified object.
-     */
-    @Override
-    public int compareTo(ControllerRegistryEntry o) {
-        return this.sequenceNumber - o.sequenceNumber;
-    }
-
-    /**
-     * Test whether some other object is "equal to" this one.
-     * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
-     * and doesn't include the controllerId.
-     *
-     * @param obj the reference object with which to compare.
-     * @return true if this object is the same as the obj argument; false
-     * otherwise.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof ControllerRegistryEntry) {
-            ControllerRegistryEntry other = (ControllerRegistryEntry) obj;
-            return this.sequenceNumber == other.sequenceNumber;
-        }
-        return false;
-    }
-
-    /**
-     * Get the hash code for the object.
-     * NOTE: the computation is based on ControllerRegistryEntry sequence
-     * numbers, and doesn't include the controller ID.
-     *
-     * @return a hash code value for this object.
-     */
-    @Override
-    public int hashCode() {
-        return Integer.valueOf(this.sequenceNumber).hashCode();
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/IControllerRegistry.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/IControllerRegistry.java
deleted file mode 100644
index 21b1709..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/IControllerRegistry.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.onlab.onos.of.controller.impl.registry;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.onlab.onos.of.controller.impl.util.InstanceId;
-
-/**
- * A registry service that allows ONOS to register controllers and switches in a
- * way that is global to the entire ONOS cluster. The registry is the arbiter
- * for allowing controllers to control switches.
- * <p/>
- * The OVS/OF1.{2,3} fault tolerance model is a switch connects to multiple
- * controllers, and the controllers send role requests to tell the switch their
- * role in controlling the switch.
- * <p/>
- * The ONOS fault tolerance model allows only a single controller to have
- * control of a switch (MASTER role) at once. Controllers therefore need a
- * mechanism that enables them to decide who should control a each switch. The
- * registry service provides this mechanism.
- */
-public interface IControllerRegistry {
-
-    /**
-     * Callback interface for control change events.
-     */
-    public interface ControlChangeCallback {
-        /**
-         * Called whenever the control changes from the point of view of the
-         * registry. The callee can check whether they have control or not using
-         * the hasControl parameter.
-         *
-         * @param dpid The switch that control has changed for
-         * @param hasControl Whether the listener now has control or not
-         */
-        void controlChanged(long dpid, boolean hasControl);
-    }
-
-    /**
-     * Request for control of a switch. This method does not block. When control
-     * for a switch changes, the controlChanged method on the callback object
-     * will be called. This happens any time the control changes while the
-     * request is still active (until releaseControl is called)
-     *
-     * @param dpid Switch to request control for
-     * @param cb Callback that will be used to notify caller of control changes
-     * @throws RegistryException Errors contacting the registry service
-     */
-    public void requestControl(long dpid, ControlChangeCallback cb)
-            throws RegistryException;
-
-    /**
-     * Stop trying to take control of a switch. This removes the entry for this
-     * controller requesting this switch in the registry. If the controller had
-     * control when this is called, another controller will now gain control of
-     * the switch. This call doesn't block.
-     *
-     * @param dpid Switch to release control of
-     */
-    public void releaseControl(long dpid);
-
-    /**
-     * Check whether the controller has control of the switch This call doesn't
-     * block.
-     *
-     * @param dpid Switch to check control of
-     * @return true if controller has control of the switch.
-     */
-    public boolean hasControl(long dpid);
-
-    /**
-     * Check whether this instance is the leader for the cluster. This call
-     * doesn't block.
-     *
-     * @return true if the instance is the leader for the cluster, otherwise
-     *         false.
-     */
-    public boolean isClusterLeader();
-
-    /**
-     * Gets the unique ID used to identify this ONOS instance in the cluster.
-     *
-     * @return Instance ID.
-     */
-    public InstanceId getOnosInstanceId();
-
-    /**
-     * Register a controller to the ONOS cluster. Must be called before the
-     * registry can be used to take control of any switches.
-     *
-     * @param controllerId A unique string ID identifying this controller in the
-     *        cluster
-     * @throws RegistryException for errors connecting to registry service,
-     *         controllerId already registered
-     */
-    public void registerController(String controllerId)
-            throws RegistryException;
-
-    /**
-     * Get all controllers in the cluster.
-     *
-     * @return Collection of controller IDs
-     * @throws RegistryException on error
-     */
-    public Collection<String> getAllControllers() throws RegistryException;
-
-    /**
-     * Get all switches in the cluster, along with which controller is in
-     * control of them (if any) and any other controllers that have requested
-     * control.
-     *
-     * @return Map of all switches.
-     */
-    public Map<String, List<ControllerRegistryEntry>> getAllSwitches();
-
-    /**
-     * Get the controller that has control of a given switch.
-     *
-     * @param dpid Switch to find controller for
-     * @return controller ID
-     * @throws RegistryException Errors contacting registry service
-     */
-    public String getControllerForSwitch(long dpid) throws RegistryException;
-
-    /**
-     * Get all switches controlled by a given controller.
-     *
-     * @param controllerId ID of the controller
-     * @return Collection of dpids
-     */
-    public Collection<Long> getSwitchesControlledByController(String controllerId);
-
-    /**
-     * Get a unique Id Block.
-     *
-     * @return Id Block.
-     */
-    public IdBlock allocateUniqueIdBlock();
-
-    /**
-     * Get next unique id and retrieve a new range of ids if needed.
-     *
-     * @param range range to use for the identifier
-     * @return Id Block.
-     */
-    public IdBlock allocateUniqueIdBlock(long range);
-
-    /**
-     * Get a globally unique ID.
-     *
-     * @return a globally unique ID.
-     */
-    public long getNextUniqueId();
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/IdBlock.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/IdBlock.java
deleted file mode 100644
index 406a60d..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/IdBlock.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.onlab.onos.of.controller.impl.registry;
-
-public class IdBlock {
-    private final long start;
-    private final long end;
-    private final long size;
-
-    public IdBlock(long start, long end, long size) {
-        this.start = start;
-        this.end = end;
-        this.size = size;
-    }
-
-    public long getStart() {
-        return start;
-    }
-
-    public long getEnd() {
-        return end;
-    }
-
-    public long getSize() {
-        return size;
-    }
-
-    @Override
-    public String toString() {
-        return "IdBlock [start=" + start + ", end=" + end + ", size=" + size
-                + "]";
-    }
-}
-
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/RegistryException.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/RegistryException.java
deleted file mode 100644
index 029f028..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/registry/RegistryException.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.onlab.onos.of.controller.impl.registry;
-
-public class RegistryException extends Exception {
-
-    private static final long serialVersionUID = -8276300722010217913L;
-
-    public RegistryException(String message) {
-        super(message);
-    }
-
-    public RegistryException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/DummySwitchForTesting.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/DummySwitchForTesting.java
deleted file mode 100644
index 2d925f8..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/DummySwitchForTesting.java
+++ /dev/null
@@ -1,360 +0,0 @@
-package org.onlab.onos.of.controller.impl.util;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Future;
-
-import org.jboss.netty.channel.Channel;
-import org.projectfloodlight.openflow.protocol.OFActionType;
-import org.projectfloodlight.openflow.protocol.OFCapabilities;
-import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
-import org.projectfloodlight.openflow.protocol.OFMessage;
-import org.projectfloodlight.openflow.protocol.OFPortDesc;
-import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFPortStatus;
-import org.projectfloodlight.openflow.protocol.OFStatsReply;
-import org.projectfloodlight.openflow.protocol.OFStatsRequest;
-import org.projectfloodlight.openflow.protocol.OFVersion;
-import org.projectfloodlight.openflow.types.DatapathId;
-import org.projectfloodlight.openflow.types.U64;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.onlab.onos.of.controller.impl.IOFSwitch;
-import org.onlab.onos.of.controller.impl.Role;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService.CounterException;
-
-public class DummySwitchForTesting implements IOFSwitch {
-
-    protected static final Logger log = LoggerFactory.getLogger(DummySwitchForTesting.class);
-
-    private Channel channel;
-    private boolean connected = false;
-    private OFVersion ofv = OFVersion.OF_10;
-
-    private Collection<OFPortDesc> ports;
-
-    private DatapathId datapathId;
-
-    private Set<OFCapabilities> capabilities;
-
-    private int buffers;
-
-    private byte tables;
-
-    private String stringId;
-
-    private Role role;
-
-    @Override
-    public void disconnectSwitch() {
-        this.channel.close();
-    }
-
-    @Override
-    public void write(OFMessage m) throws IOException {
-        this.channel.write(m);
-
-    }
-
-    @Override
-    public void write(List<OFMessage> msglist) throws IOException {
-        for (OFMessage m : msglist) {
-            this.channel.write(m);
-        }
-
-    }
-
-    @Override
-    public Date getConnectedSince() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getNextTransactionId() {
-        return 0;
-    }
-
-    @Override
-    public boolean isConnected() {
-        return this.connected;
-    }
-
-    @Override
-    public void setConnected(boolean connected) {
-        this.connected  = connected;
-
-    }
-
-    @Override
-    public void flush() {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setChannel(Channel channel) {
-        this.channel = channel;
-
-    }
-
-    @Override
-    public long getId() {
-        if (this.stringId == null) {
-            throw new RuntimeException("Features reply has not yet been set");
-        }
-        return this.datapathId.getLong();
-    }
-
-    @Override
-    public String getStringId() {
-        // TODO Auto-generated method stub
-        return "DummySwitch";
-    }
-
-    @Override
-    public int getNumBuffers() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public Set<OFCapabilities> getCapabilities() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public byte getNumTables() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public OFDescStatsReply getSwitchDescription() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void cancelFeaturesReply(int transactionId) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public Set<OFActionType> getActions() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void setOFVersion(OFVersion version) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public OFVersion getOFVersion() {
-        return this.ofv;
-    }
-
-    @Override
-    public Collection<OFPortDesc> getEnabledPorts() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Collection<Integer> getEnabledPortNumbers() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public OFPortDesc getPort(int portNumber) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public OFPortDesc getPort(String portName) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public OrderedCollection<PortChangeEvent> processOFPortStatus(
-            OFPortStatus ps) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Collection<OFPortDesc> getPorts() {
-        return ports;
-    }
-
-    @Override
-    public boolean portEnabled(int portName) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public OrderedCollection<PortChangeEvent> setPorts(
-            Collection<OFPortDesc> p) {
-        this.ports = p;
-        return null;
-    }
-
-    @Override
-    public Map<Object, Object> getAttributes() {
-        return null;
-    }
-
-    @Override
-    public boolean hasAttribute(String name) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public Object getAttribute(String name) {
-        return Boolean.FALSE;
-    }
-
-    @Override
-    public void setAttribute(String name, Object value) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public Object removeAttribute(String name) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void deliverStatisticsReply(OFMessage reply) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void cancelStatisticsReply(int transactionId) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void cancelAllStatisticsReplies() {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
-            throws IOException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void clearAllFlowMods() {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public Role getRole() {
-        return this.role;
-    }
-
-    @Override
-    public void setRole(Role role) {
-        this.role = role;
-    }
-
-    @Override
-    public U64 getNextGenerationId() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void setDebugCounterService(IDebugCounterService debugCounter)
-            throws CounterException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void startDriverHandshake() throws IOException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean isDriverHandshakeComplete() {
-        return true;
-    }
-
-    @Override
-    public void processDriverHandshakeMessage(OFMessage m) {
-
-    }
-
-    @Override
-    public void setTableFull(boolean isFull) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setFeaturesReply(OFFeaturesReply featuresReply) {
-        if (featuresReply == null) {
-            log.error("Error setting featuresReply for switch: {}", getStringId());
-            return;
-        }
-        this.datapathId = featuresReply.getDatapathId();
-        this.capabilities = featuresReply.getCapabilities();
-        this.buffers = (int) featuresReply.getNBuffers();
-        this.tables = (byte) featuresReply.getNTables();
-        this.stringId = this.datapathId.toString();
-
-    }
-
-    @Override
-    public void setPortDescReply(OFPortDescStatsReply portDescReply) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void handleMessage(OFMessage m) {
-        log.info("Got packet {} but I am dumb so I don't know what to do.", m);
-    }
-
-    @Override
-    public boolean portEnabled(String portName) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public OrderedCollection<PortChangeEvent> comparePorts(
-            Collection<OFPortDesc> p) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/EnumBitmaps.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/EnumBitmaps.java
deleted file mode 100644
index c7734c0..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/EnumBitmaps.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package org.onlab.onos.of.controller.impl.util;
-
-import java.util.EnumSet;
-import java.util.Set;
-
-/**
- * A utility class to convert between integer based bitmaps for (OpenFlow)
- * flags and Enum and EnumSet based representations.
- *
- * The enum used to represent individual flags needs to implement the
- * BitmapableEnum interface.
- *
- * Example:
- * {@code
- *   int bitmap = 0x11; // OFPPC_PORT_DOWN | OFPPC_NO_STP
- *   EnumSet<OFPortConfig> s = toEnumSet(OFPortConfig.class, bitmap);
- *   // s will contain OFPPC_PORT_DOWN and OFPPC_NO_STP
- * }
- *
- * {@code
- *    EnumSet<OFPortConfig> s = EnumSet.of(OFPPC_NO_STP, OFPPC_PORT_DOWN);
- *    int bitmap = toBitmap(s); // returns 0x11
- * }
- *
- */
-public final class EnumBitmaps {
-
-
-    private EnumBitmaps() { }
-
-    /**
-     * Enums used to represent individual flags needs to implement this
-     * interface.
-     */
-    public interface BitmapableEnum {
-        /** Return the value in the bitmap that the enum constant represents.
-         * The returned value must have only a single bit set. E.g.,1 << 3
-         */
-        int getValue();
-    }
-
-
-    /**
-     * Convert an integer bitmap to an EnumSet.
-     *
-     * See class description for example
-     * @param type The Enum class to use. Must implement BitmapableEnum
-     * @param bitmap The integer bitmap
-     * @return A newly allocated EnumSet representing the bits set in the
-     * bitmap
-     * @throws NullPointerException if type is null
-     * @throws IllegalArgumentException if any enum constant from type has
-     * more than one bit set.
-     * @throws IllegalArgumentException if the bitmap has any bits set not
-     * represented by an enum constant.
-     */
-    public static <E extends Enum<E> & BitmapableEnum>
-            EnumSet<E> toEnumSet(Class<E> type, int bitmap) {
-        if (type == null) {
-            throw new NullPointerException("Given enum type must not be null");
-        }
-        EnumSet<E> s = EnumSet.noneOf(type);
-        // allSetBitmap will eventually have all valid bits for the given
-        // type set.
-        int allSetBitmap = 0;
-        for (E element: type.getEnumConstants()) {
-            if (Integer.bitCount(element.getValue()) != 1) {
-                String msg = String.format("The %s (%x) constant of the " +
-                        "enum %s is supposed to represent a bitmap entry but " +
-                        "has more than one bit set.",
-                        element.toString(), element.getValue(), type.getName());
-                throw new IllegalArgumentException(msg);
-            }
-            allSetBitmap |= element.getValue();
-            if ((bitmap & element.getValue()) != 0) {
-                s.add(element);
-            }
-        }
-        if (((~allSetBitmap) & bitmap) != 0) {
-            // check if only valid flags are set in the given bitmap
-            String msg = String.format("The bitmap %x for enum %s has " +
-                    "bits set that are presented by any enum constant",
-                    bitmap, type.getName());
-            throw new IllegalArgumentException(msg);
-        }
-        return s;
-    }
-
-    /**
-     * Return the bitmap mask with all possible bits set. E.g., If a bitmap
-     * has the individual flags 0x1, 0x2, and 0x8 (note the missing 0x4) then
-     * the mask will be 0xb (1011 binary)
-     *
-     * @param type The Enum class to use. Must implement BitmapableEnum
-     * @throws NullPointerException if type is null
-     * @throws IllegalArgumentException if any enum constant from type has
-     * more than one bit set
-     * @return an integer with all possible bits for the given bitmap enum
-     * type set.
-     */
-    public static <E extends Enum<E> & BitmapableEnum>
-            int getMask(Class<E> type) {
-        if (type == null) {
-            throw new NullPointerException("Given enum type must not be null");
-        }
-        // allSetBitmap will eventually have all valid bits for the given
-        // type set.
-        int allSetBitmap = 0;
-        for (E element: type.getEnumConstants()) {
-            if (Integer.bitCount(element.getValue()) != 1) {
-                String msg = String.format("The %s (%x) constant of the " +
-                        "enum %s is supposed to represent a bitmap entry but " +
-                        "has more than one bit set.",
-                        element.toString(), element.getValue(), type.getName());
-                throw new IllegalArgumentException(msg);
-            }
-            allSetBitmap |= element.getValue();
-        }
-        return allSetBitmap;
-    }
-
-    /**
-     * Convert the given EnumSet to the integer bitmap representation.
-     * @param set The EnumSet to convert. The enum must implement
-     * BitmapableEnum
-     * @return the integer bitmap
-     * @throws IllegalArgumentException if an enum constant from the set (!) has
-     * more than one bit set
-     * @throws NullPointerException if the set is null
-     */
-    public static <E extends Enum<E> & BitmapableEnum>
-            int toBitmap(Set<E> set) {
-        if (set == null) {
-            throw new NullPointerException("Given set must not be null");
-        }
-        int bitmap = 0;
-        for (E element: set) {
-            if (Integer.bitCount(element.getValue()) != 1) {
-                String msg = String.format("The %s (%x) constant in the set " +
-                        "is supposed to represent a bitmap entry but " +
-                        "has more than one bit set.",
-                        element.toString(), element.getValue());
-                throw new IllegalArgumentException(msg);
-            }
-            bitmap |= element.getValue();
-        }
-        return bitmap;
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/FilterIterator.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/FilterIterator.java
deleted file mode 100644
index 319aae8..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/FilterIterator.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- *    Copyright 2012, Big Switch Networks, Inc.
- *    Originally created by David Erickson, Stanford University
- *
- *    Licensed under the Apache License, Version 2.0 (the "License"); you may
- *    not use this file except in compliance with the License. You may obtain
- *    a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *    License for the specific language governing permissions and limitations
- *    under the License.
- **/
-
-package org.onlab.onos.of.controller.impl.util;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * An iterator that will filter values from an iterator and return only
- * those values that match the predicate.
- */
-public abstract class FilterIterator<T> implements Iterator<T> {
-    protected Iterator<T> subIterator;
-    protected T next;
-
-    /**
-     * Construct a filter iterator from the given sub iterator.
-     *
-     * @param subIterator the sub iterator over which we'll filter
-     */
-    public FilterIterator(Iterator<T> subIterator) {
-        super();
-        this.subIterator = subIterator;
-    }
-
-    /**
-     * Check whether the given value should be returned by the
-     * filter.
-     *
-     * @param value the value to check
-     * @return true if the value should be included
-     */
-    protected abstract boolean matches(T value);
-
-    // ***********
-    // Iterator<T>
-    // ***********
-
-    @Override
-    public boolean hasNext() {
-        if (next != null) {
-            return true;
-        }
-
-        while (subIterator.hasNext()) {
-            next = subIterator.next();
-            if (matches(next)) {
-                return true;
-            }
-        }
-        next = null;
-        return false;
-    }
-
-    @Override
-    public T next() {
-        if (hasNext()) {
-            T cur = next;
-            next = null;
-            return cur;
-        }
-        throw new NoSuchElementException();
-    }
-
-    @Override
-    public void remove() {
-        throw new UnsupportedOperationException();
-    }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/InstanceId.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/InstanceId.java
deleted file mode 100644
index 4a7892e..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/InstanceId.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.onlab.onos.of.controller.impl.util;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * The class representing an ONOS Instance ID.
- *
- * This class is immutable.
- */
-public final class InstanceId {
-    private final String id;
-
-    /**
-     * Constructor from a string value.
-     *
-     * @param id the value to use.
-     */
-    public InstanceId(String id) {
-        this.id = checkNotNull(id);
-        checkArgument(!id.isEmpty(), "Empty ONOS Instance ID");
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-
-        if (!(obj instanceof InstanceId)) {
-            return false;
-        }
-
-        InstanceId that = (InstanceId) obj;
-        return this.id.equals(that.id);
-    }
-
-    @Override
-    public String toString() {
-        return id;
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/IterableIterator.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/IterableIterator.java
deleted file mode 100644
index a59b244..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/IterableIterator.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- *    Copyright 2012 Big Switch Networks, Inc.
- *    Originally created by David Erickson, Stanford University
- *
- *    Licensed under the Apache License, Version 2.0 (the "License"); you may
- *    not use this file except in compliance with the License. You may obtain
- *    a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *    License for the specific language governing permissions and limitations
- *    under the License.
- **/
-
-package org.onlab.onos.of.controller.impl.util;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Iterator over all values in an iterator of iterators.
- *
- * @param <T> the type of elements returned by this iterator
- */
-public class IterableIterator<T> implements Iterator<T> {
-    Iterator<? extends Iterable<T>> subIterator;
-    Iterator<T> current = null;
-
-    public IterableIterator(Iterator<? extends Iterable<T>> subIterator) {
-        super();
-        this.subIterator = subIterator;
-    }
-
-    @Override
-    public boolean hasNext() {
-        if (current == null) {
-            if (subIterator.hasNext()) {
-                current = subIterator.next().iterator();
-            } else {
-                return false;
-            }
-        }
-        while (!current.hasNext() && subIterator.hasNext()) {
-            current = subIterator.next().iterator();
-        }
-
-        return current.hasNext();
-    }
-
-    @Override
-    public T next() {
-        if (hasNext()) {
-            return current.next();
-        }
-        throw new NoSuchElementException();
-    }
-
-    @Override
-    public void remove() {
-        if (hasNext()) {
-            current.remove();
-        }
-        throw new NoSuchElementException();
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/LRUHashMap.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/LRUHashMap.java
deleted file mode 100644
index 866794f..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/LRUHashMap.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- *    Copyright 2011, Big Switch Networks, Inc.
- *    Originally created by David Erickson, Stanford University
- *
- *    Licensed under the Apache License, Version 2.0 (the "License"); you may
- *    not use this file except in compliance with the License. You may obtain
- *    a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *    License for the specific language governing permissions and limitations
- *    under the License.
- **/
-
-package org.onlab.onos.of.controller.impl.util;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-public class LRUHashMap<K, V> extends LinkedHashMap<K, V> {
-
-    private static final long serialVersionUID = 1L;
-
-    private final int capacity;
-
-    public LRUHashMap(int capacity) {
-        super(capacity + 1, 0.75f, true);
-        this.capacity = capacity;
-    }
-
-    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
-        return size() > capacity;
-    }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/LinkedHashSetWrapper.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/LinkedHashSetWrapper.java
deleted file mode 100644
index 1778d06..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/LinkedHashSetWrapper.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.onlab.onos.of.controller.impl.util;
-
-import java.util.Collection;
-import java.util.LinkedHashSet;
-
-import com.google.common.collect.ForwardingCollection;
-
-/**
- * A simple wrapper / forwarder that forwards all calls to a LinkedHashSet.
- * This wrappers sole reason for existence is to implement the
- * OrderedCollection marker interface.
- *
- */
-public class LinkedHashSetWrapper<E>
-        extends ForwardingCollection<E> implements OrderedCollection<E> {
-    private final Collection<E> delegate;
-
-    public LinkedHashSetWrapper() {
-        super();
-        this.delegate = new LinkedHashSet<E>();
-    }
-
-    public LinkedHashSetWrapper(Collection<? extends E> c) {
-        super();
-        this.delegate = new LinkedHashSet<E>(c);
-    }
-
-    @Override
-    protected Collection<E> delegate() {
-        return this.delegate;
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/MultiIterator.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/MultiIterator.java
deleted file mode 100644
index 7b709e9..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/MultiIterator.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- *    Copyright 2012 Big Switch Networks, Inc.
- *    Originally created by David Erickson, Stanford University
- *
- *    Licensed under the Apache License, Version 2.0 (the "License"); you may
- *    not use this file except in compliance with the License. You may obtain
- *    a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *    License for the specific language governing permissions and limitations
- *    under the License.
- **/
-
-package org.onlab.onos.of.controller.impl.util;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Iterator over all values in an iterator of iterators.
- *
- * @param <T> the type of elements returned by this iterator
- */
-public class MultiIterator<T> implements Iterator<T> {
-    Iterator<Iterator<T>> subIterator;
-    Iterator<T> current = null;
-
-    public MultiIterator(Iterator<Iterator<T>> subIterator) {
-        super();
-        this.subIterator = subIterator;
-    }
-
-    @Override
-    public boolean hasNext() {
-        if (current == null) {
-            if (subIterator.hasNext()) {
-                current = subIterator.next();
-            } else {
-                return false;
-            }
-        }
-        while (!current.hasNext() && subIterator.hasNext()) {
-            current = subIterator.next();
-        }
-
-        return current.hasNext();
-    }
-
-    @Override
-    public T next() {
-        if (hasNext()) {
-            return current.next();
-        }
-        throw new NoSuchElementException();
-    }
-
-    @Override
-    public void remove() {
-        if (hasNext()) {
-            current.remove();
-        }
-        throw new NoSuchElementException();
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/OrderedCollection.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/OrderedCollection.java
deleted file mode 100644
index 9dce568..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/util/OrderedCollection.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.onlab.onos.of.controller.impl.util;
-
-import java.util.Collection;
-
-/**
- * A marker interface indicating that this Collection defines a particular
- * iteration order. The details about the iteration order are specified by
- * the concrete implementation.
- *
- * @param <E>
- */
-public interface OrderedCollection<E> extends Collection<E> {
-
-}
diff --git a/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/ControllerTest.java b/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/ControllerTest.java
deleted file mode 100644
index 5de3647..0000000
--- a/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/ControllerTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- *    Copyright 2011, Big Switch Networks, Inc.
- *    Originally created by David Erickson, Stanford University
- *
- *    Licensed under the Apache License, Version 2.0 (the "License"); you may
- *    not use this file except in compliance with the License. You may obtain
- *    a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *    License for the specific language governing permissions and limitations
- *    under the License.
- **/
-
-package org.onlab.onos.of.controller.impl.internal;
-
-import junit.framework.TestCase;
-import org.onlab.onos.of.controller.impl.IOFSwitch;
-
-import org.easymock.EasyMock;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-
-public class ControllerTest extends TestCase {
-
-    private Controller controller;
-    private IOFSwitch sw;
-    private OFChannelHandler h;
-
-    @Override
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        sw = EasyMock.createMock(IOFSwitch.class);
-        h = EasyMock.createMock(OFChannelHandler.class);
-        controller = new Controller();
-        ControllerRunThread t = new ControllerRunThread();
-        t.start();
-        /*
-         * Making sure the thread is properly started before making calls
-         * to controller class.
-         */
-        Thread.sleep(200);
-    }
-
-    /**
-     * Starts the base mocks used in these tests.
-     */
-    private void startMocks() {
-        EasyMock.replay(sw, h);
-    }
-
-    /**
-     * Reset the mocks to a known state.
-     * Automatically called after tests.
-     */
-    @After
-    private void resetMocks() {
-        EasyMock.reset(sw);
-    }
-
-    /**
-     * Fetches the controller instance.
-     * @return the controller
-     */
-    public Controller getController() {
-        return controller;
-    }
-
-    /**
-     * Run the controller's main loop so that updates are processed.
-     */
-    protected class ControllerRunThread extends Thread {
-        @Override
-        public void run() {
-            controller.openFlowPort = 0; // Don't listen
-            controller.activate();
-        }
-    }
-
-    /**
-     * Verify that we are able to add a switch that just connected.
-     * If it already exists then this should fail
-     *
-     * @throws Exception error
-     */
-    @Test
-    public void testAddConnectedSwitches() throws Exception {
-        startMocks();
-        assertTrue(controller.addConnectedSwitch(0, h));
-        assertFalse(controller.addConnectedSwitch(0, h));
-    }
-
-    /**
-     * Add active master but cannot re-add active master.
-     * @throws Exception an error occurred.
-     */
-    @Test
-    public void testAddActivatedMasterSwitch() throws Exception {
-        startMocks();
-        controller.addConnectedSwitch(0, h);
-        assertTrue(controller.addActivatedMasterSwitch(0, sw));
-        assertFalse(controller.addActivatedMasterSwitch(0, sw));
-    }
-
-    /**
-     * Tests that an activated switch can be added but cannot be re-added.
-     *
-     * @throws Exception an error occurred
-     */
-    @Test
-    public void testAddActivatedEqualSwitch() throws Exception {
-        startMocks();
-        controller.addConnectedSwitch(0, h);
-        assertTrue(controller.addActivatedEqualSwitch(0, sw));
-        assertFalse(controller.addActivatedEqualSwitch(0, sw));
-    }
-
-    /**
-     * Move an equal switch to master.
-     * @throws Exception an error occurred
-     */
-    @Test
-    public void testTranstitionToMaster() throws Exception {
-        startMocks();
-        controller.addConnectedSwitch(0, h);
-        controller.addActivatedEqualSwitch(0, sw);
-        controller.transitionToMasterSwitch(0);
-        assertNotNull(controller.getMasterSwitch(0));
-    }
-
-    /**
-     * Transition a master switch to equal state.
-     * @throws Exception an error occurred
-     */
-    @Test
-    public void testTranstitionToEqual() throws Exception {
-        startMocks();
-        controller.addConnectedSwitch(0, h);
-        controller.addActivatedMasterSwitch(0, sw);
-        controller.transitionToEqualSwitch(0);
-        assertNotNull(controller.getEqualSwitch(0));
-    }
-
-    /**
-     * Remove the switch from the controller instance.
-     * @throws Exception an error occurred
-     */
-    @Test
-    public void testRemoveSwitch() throws Exception {
-        sw.cancelAllStatisticsReplies();
-        EasyMock.expectLastCall().once();
-        sw.setConnected(false);
-        EasyMock.expectLastCall().once();
-        startMocks();
-        controller.addConnectedSwitch(0, h);
-        controller.addActivatedMasterSwitch(0, sw);
-        controller.removeConnectedSwitch(0);
-        assertNull(controller.getSwitch(0));
-        EasyMock.verify(sw, h);
-    }
-}
diff --git a/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandlerTest.java b/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandlerTest.java
deleted file mode 100644
index f267923..0000000
--- a/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandlerTest.java
+++ /dev/null
@@ -1,1569 +0,0 @@
-package org.onlab.onos.of.controller.impl.internal;
-
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.onlab.onos.of.controller.impl.IOFSwitch;
-import org.onlab.onos.of.controller.impl.Role;
-import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter;
-import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
-import org.onlab.onos.of.controller.impl.internal.OFChannelHandler.RoleRecvStatus;
-
-import org.easymock.Capture;
-import org.easymock.CaptureType;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ChannelPipeline;
-import org.jboss.netty.channel.ChannelStateEvent;
-import org.jboss.netty.channel.ExceptionEvent;
-import org.jboss.netty.channel.MessageEvent;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFExperimenter;
-import org.projectfloodlight.openflow.protocol.OFFactories;
-import org.projectfloodlight.openflow.protocol.OFFactory;
-import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
-import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
-import org.projectfloodlight.openflow.protocol.OFHelloElem;
-import org.projectfloodlight.openflow.protocol.OFMessage;
-import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
-import org.projectfloodlight.openflow.protocol.OFPacketIn;
-import org.projectfloodlight.openflow.protocol.OFPacketInReason;
-import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFSetConfig;
-import org.projectfloodlight.openflow.protocol.OFStatsReply;
-import org.projectfloodlight.openflow.protocol.OFStatsRequest;
-import org.projectfloodlight.openflow.protocol.OFStatsType;
-import org.projectfloodlight.openflow.protocol.OFType;
-import org.projectfloodlight.openflow.protocol.OFVersion;
-import org.projectfloodlight.openflow.types.DatapathId;
-import org.projectfloodlight.openflow.types.U32;
-
-/**
- * Channel handler deals with the switch connection and dispatches
- * switch messages to the appropriate locations. These Unit Testing cases
- * test the channeler state machine and role changer. In the first release,
- * we will focus on OF version 1.0. we will add the testing case for
- * version 1.3 later.
- */
-public class OFChannelHandlerTest {
-    private Controller controller;
-    private IDebugCounterService debugCounterService;
-    private OFChannelHandler handler;
-    private Channel channel;
-    private ChannelHandlerContext ctx;
-    private MessageEvent messageEvent;
-    private ChannelStateEvent channelStateEvent;
-    private ChannelPipeline pipeline;
-    private Capture<ExceptionEvent> exceptionEventCapture;
-    private Capture<List<OFMessage>> writeCapture;
-    private OFFeaturesReply featuresReply;
-    private Set<Integer> seenXids = null;
-    private IOFSwitch swImplBase;
-    private OFVersion ofVersion = OFVersion.OF_10;
-    private OFFactory factory13;
-    private OFFactory factory10;
-    private OFFactory factory;
-
-    @Before
-    public void setUp() throws Exception {
-        controller = createMock(Controller.class);
-        ctx = createMock(ChannelHandlerContext.class);
-        channelStateEvent = createMock(ChannelStateEvent.class);
-        channel = createMock(Channel.class);
-        messageEvent = createMock(MessageEvent.class);
-        exceptionEventCapture = new Capture<ExceptionEvent>(CaptureType.ALL);
-        pipeline = createMock(ChannelPipeline.class);
-        writeCapture = new Capture<List<OFMessage>>(CaptureType.ALL);
-        swImplBase = createMock(IOFSwitch.class);
-        seenXids = null;
-        factory13 = OFFactories.getFactory(OFVersion.OF_13);
-        factory10 = OFFactories.getFactory(OFVersion.OF_10);
-        factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
-
-        // TODO: should mock IDebugCounterService and make sure
-        // the expected counters are updated.
-        debugCounterService = new DebugCounter();
-        Controller.Counters counters =
-                new Controller.Counters();
-        counters.createCounters(debugCounterService);
-        expect(controller.getCounters()).andReturn(counters).anyTimes();
-        expect(controller.getOFMessageFactory10()).andReturn(factory10)
-            .anyTimes();
-        expect(controller.getOFMessageFactory13()).andReturn(factory13)
-            .anyTimes();
-        expect(controller.addConnectedSwitch(2000, handler)).andReturn(true)
-            .anyTimes();
-        replay(controller);
-        handler = new OFChannelHandler(controller);
-        verify(controller);
-        reset(controller);
-
-        resetChannel();
-
-        // replay controller. Reset it if you need more specific behavior
-        replay(controller);
-
-        // replay switch. Reset it if you need more specific behavior
-        replay(swImplBase);
-
-        // Mock ctx and channelStateEvent
-        expect(ctx.getChannel()).andReturn(channel).anyTimes();
-        expect(channelStateEvent.getChannel()).andReturn(channel).anyTimes();
-        replay(ctx, channelStateEvent);
-
-        /* Setup an exception event capture on the channel. Right now
-         * we only expect exception events to be send up the channel.
-         * However, it's easy to extend to other events if we need it
-         */
-        pipeline.sendUpstream(capture(exceptionEventCapture));
-        expectLastCall().anyTimes();
-        replay(pipeline);
-        featuresReply = (OFFeaturesReply) buildOFMessage(OFType.FEATURES_REPLY);
-    }
-
-    @After
-    public void tearDown() {
-        /* ensure no exception was thrown */
-        if (exceptionEventCapture.hasCaptured()) {
-            Throwable ex = exceptionEventCapture.getValue().getCause();
-            throw new AssertionError("Unexpected exception: " +
-                    ex.getClass().getName() + "(" + ex + ")");
-        }
-        assertFalse("Unexpected messages have been captured",
-                writeCapture.hasCaptured());
-        // verify all mocks.
-        verify(channel);
-        verify(messageEvent);
-        verify(controller);
-        verify(ctx);
-        verify(channelStateEvent);
-        verify(pipeline);
-        verify(swImplBase);
-
-    }
-
-    /**
-     * Reset the channel mock and set basic method call expectations.
-     *
-     **/
-    void resetChannel() {
-        reset(channel);
-        expect(channel.getPipeline()).andReturn(pipeline).anyTimes();
-        expect(channel.getRemoteAddress()).andReturn(null).anyTimes();
-    }
-
-    /**
-     * reset, setup, and replay the messageEvent mock for the given
-     * messages.
-     */
-    void setupMessageEvent(List<OFMessage> messages) {
-        reset(messageEvent);
-        expect(messageEvent.getMessage()).andReturn(messages).atLeastOnce();
-        replay(messageEvent);
-    }
-
-    /**
-     * reset, setup, and replay the messageEvent mock for the given
-     * messages, mock controller  send message to channel handler.
-     *
-     * This method will reset, start replay on controller, and then verify
-     */
-    void sendMessageToHandlerWithControllerReset(List<OFMessage> messages)
-            throws Exception {
-        verify(controller);
-        reset(controller);
-
-        sendMessageToHandlerNoControllerReset(messages);
-    }
-
-    /**
-     * reset, setup, and replay the messageEvent mock for the given
-     * messages, mock controller  send message to channel handler.
-     *
-     * This method will start replay on controller, and then verify
-     */
-    void sendMessageToHandlerNoControllerReset(List<OFMessage> messages)
-            throws Exception {
-        setupMessageEvent(messages);
-
-        expect(controller.addConnectedSwitch(1000, handler))
-        .andReturn(true).anyTimes();
-        replay(controller);
-
-        handler.messageReceived(ctx, messageEvent);
-        verify(controller);
-    }
-
-    /**
-     * Extract the list of OFMessages that was captured by the Channel.write()
-     * capture. Will check that something was actually captured first. We'll
-     * collapse the messages from multiple writes into a single list of
-     * OFMessages.
-     * Resets the channelWriteCapture.
-     */
-    List<OFMessage> getMessagesFromCapture() {
-        List<OFMessage> msgs = new ArrayList<OFMessage>();
-
-        assertTrue("No write on channel was captured",
-                writeCapture.hasCaptured());
-        List<List<OFMessage>> capturedVals = writeCapture.getValues();
-
-        for (List<OFMessage> oneWriteList: capturedVals) {
-            msgs.addAll(oneWriteList);
-        }
-        writeCapture.reset();
-        return msgs;
-    }
-
-
-    /**
-     * Verify that the given exception event capture (as returned by
-     * getAndInitExceptionCapture) has thrown an exception of the given
-     * expectedExceptionClass.
-     * Resets the capture
-     */
-    void verifyExceptionCaptured(
-            Class<? extends Throwable> expectedExceptionClass) {
-        assertTrue("Excpected exception not thrown",
-                exceptionEventCapture.hasCaptured());
-        Throwable caughtEx = exceptionEventCapture.getValue().getCause();
-        assertEquals(expectedExceptionClass, caughtEx.getClass());
-        exceptionEventCapture.reset();
-    }
-
-    /**
-     * Make sure that the transaction ids in the given messages are
-     * not 0 and differ between each other.
-     * While it's not a defect per se if the xids are we want to ensure
-     * we use different ones for each message we send.
-     */
-    void verifyUniqueXids(List<OFMessage> msgs) {
-        if (seenXids == null) {
-            seenXids = new HashSet<Integer>();
-        }
-        for (OFMessage m: msgs)  {
-            int xid = (int) m.getXid();
-            assertTrue("Xid in messags is 0", xid != 0);
-            assertFalse("Xid " + xid + " has already been used",
-                    seenXids.contains(xid));
-            seenXids.add(xid);
-        }
-    }
-
-
-
-    public void testInitState() throws Exception {
-        OFMessage m = buildOFMessage(OFType.HELLO);
-
-        expect(messageEvent.getMessage()).andReturn(null);
-        replay(channel, messageEvent);
-
-        // We don't expect to receive /any/ messages in init state since
-        // channelConnected moves us to a different state
-        sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
-
-        verifyExceptionCaptured(SwitchStateException.class);
-        assertEquals(OFChannelHandler.ChannelState.INIT,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * move the channel from scratch to WAIT_HELLO state.
-     *
-     */
-    @Test
-    public void moveToWaitHello() throws Exception {
-        resetChannel();
-        channel.write(capture(writeCapture));
-        expectLastCall().andReturn(null).once();
-        replay(channel);
-        // replay unused mocks
-        replay(messageEvent);
-
-        handler.channelConnected(ctx, channelStateEvent);
-
-        List<OFMessage> msgs = getMessagesFromCapture();
-        assertEquals(1, msgs.size());
-        assertEquals(OFType.HELLO, msgs.get(0).getType());
-        assertEquals(OFChannelHandler.ChannelState.WAIT_HELLO,
-                handler.getStateForTesting());
-        //Should verify that the Hello received from the controller
-        //is ALWAYS OF1.3 hello regardless of the switch version
-        assertEquals(OFVersion.OF_13, msgs.get(0).getVersion());
-        verifyUniqueXids(msgs);
-    }
-
-
-    /**
-     * Move the channel from scratch to WAIT_FEATURES_REPLY state.
-     * Builds on moveToWaitHello().
-     * adds testing for WAIT_HELLO state.
-     */
-    @Test
-    public void moveToWaitFeaturesReply() throws Exception {
-        moveToWaitHello();
-        resetChannel();
-        channel.write(capture(writeCapture));
-        expectLastCall().andReturn(null).atLeastOnce();
-        replay(channel);
-
-        OFMessage hello = buildOFMessage(OFType.HELLO);
-        sendMessageToHandlerWithControllerReset(Collections.singletonList(hello));
-
-        List<OFMessage> msgs = getMessagesFromCapture();
-        assertEquals(1, msgs.size());
-        assertEquals(OFType.FEATURES_REQUEST, msgs.get(0).getType());
-        if (ofVersion == OFVersion.OF_10) {
-            assertEquals(OFVersion.OF_10, msgs.get(0).getVersion());
-        }
-        verifyUniqueXids(msgs);
-
-        assertEquals(OFChannelHandler.ChannelState.WAIT_FEATURES_REPLY,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to WAIT_CONFIG_REPLY state.
-     * Builds on moveToWaitFeaturesReply.
-     * adds testing for WAIT_FEATURES_REPLY state.
-     */
-    @Test
-    public void moveToWaitConfigReply() throws Exception {
-        moveToWaitFeaturesReply();
-
-        resetChannel();
-        channel.write(capture(writeCapture));
-        expectLastCall().andReturn(null).atLeastOnce();
-        replay(channel);
-
-        sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(featuresReply));
-        List<OFMessage> msgs = getMessagesFromCapture();
-        assertEquals(3, msgs.size());
-        assertEquals(OFType.SET_CONFIG, msgs.get(0).getType());
-        OFSetConfig sc = (OFSetConfig) msgs.get(0);
-        assertEquals((short) 0xffff, sc.getMissSendLen());
-        assertEquals(OFType.BARRIER_REQUEST, msgs.get(1).getType());
-        assertEquals(OFType.GET_CONFIG_REQUEST, msgs.get(2).getType());
-        verifyUniqueXids(msgs);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_CONFIG_REPLY,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to WAIT_DESCRIPTION_STAT_REPLY state.
-     * Builds on moveToWaitConfigReply().
-     * adds testing for WAIT_CONFIG_REPLY state.
-     */
-    @Test
-    public void moveToWaitDescriptionStatReply() throws Exception {
-        moveToWaitConfigReply();
-        resetChannel();
-        channel.write(capture(writeCapture));
-        expectLastCall().andReturn(null).atLeastOnce();
-        replay(channel);
-
-        OFGetConfigReply cr = (OFGetConfigReply) buildOFMessage(OFType.GET_CONFIG_REPLY);
-
-        sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(cr));
-
-        List<OFMessage> msgs = getMessagesFromCapture();
-        assertEquals(1, msgs.size());
-        assertEquals(OFType.STATS_REQUEST, msgs.get(0).getType());
-        OFStatsRequest<?> sr = (OFStatsRequest<?>) msgs.get(0);
-        assertEquals(OFStatsType.DESC, sr.getStatsType());
-        verifyUniqueXids(msgs);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_DESCRIPTION_STAT_REPLY,
-                handler.getStateForTesting());
-    }
-
-
-    private OFStatsReply createDescriptionStatsReply() throws IOException {
-        OFStatsReply sr = (OFStatsReply) buildOFMessage(OFType.STATS_REPLY);
-        return sr;
-    }
-
-    /**
-     * Move the channel from scratch to WAIT_INITIAL_ROLE state.
-     * for a switch that does not have a sub-handshake.
-     * Builds on moveToWaitDescriptionStatReply().
-     * adds testing for WAIT_DESCRIPTION_STAT_REPLY state.
-     *
-     */
-    @Test
-    public void moveToWaitInitialRole()
-            throws Exception {
-        moveToWaitDescriptionStatReply();
-
-        long xid = 2000;
-
-        // build the stats reply
-        OFStatsReply sr = createDescriptionStatsReply();
-
-        resetChannel();
-        replay(channel);
-
-        setupMessageEvent(Collections.<OFMessage>singletonList(sr));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-        controller.submitRegistryRequest(1000);
-        expectLastCall().once();
-        replay(controller);
-
-        //TODO: With the description stats message you are sending in the test,
-        //you will end up with an OFSwitchImplBase object
-        //which by default does NOT support the nicira role messages.
-        //If you wish to test the case where Nicira role messages are supported,
-        //then make a comment here that states that this is different
-        //from the default behavior of switchImplbase /or/
-        //send the right desc-stats (for example send what is expected from OVS 1.0)
-
-        if (ofVersion == OFVersion.OF_10) {
-            expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
-            .andReturn(true).once();
-
-            swImplBase.write(capture(writeCapture));
-            expectLastCall().anyTimes();
-        }
-
-        swImplBase.setOFVersion(ofVersion);
-        expectLastCall().once();
-        swImplBase.setConnected(true);
-        expectLastCall().once();
-        swImplBase.setChannel(channel);
-        expectLastCall().once();
-        swImplBase.setDebugCounterService(controller.getDebugCounter());
-        expectLastCall().once();
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        swImplBase.setRole(Role.EQUAL);
-        expectLastCall().once();
-
-        expect(swImplBase.getNextTransactionId())
-        .andReturn((int) xid).anyTimes();
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-
-        swImplBase.setFeaturesReply(featuresReply);
-        expectLastCall().once();
-        swImplBase.setPortDescReply((OFPortDescStatsReply) null);
-        replay(swImplBase);
-
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-
-        List<OFMessage> msgs = getMessagesFromCapture();
-        assertEquals(1, msgs.size());
-        assertEquals(OFType.EXPERIMENTER, msgs.get(0).getType());
-        verifyNiciraMessage((OFExperimenter) msgs.get(0));
-
-        verify(controller);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to.
-     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
-     * Builds on moveToWaitInitialRole().
-     */
-    @Test
-    public void moveToWaitSubHandshake()
-            throws Exception {
-        moveToWaitInitialRole();
-
-        int xid = 2000;
-        resetChannel();
-        replay(channel);
-
-        reset(swImplBase);
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                handler.getStateForTesting());
-
-        // build the stats reply
-        OFStatsReply sr = createDescriptionStatsReply();
-        OFMessage rr = getRoleReply(xid, Role.SLAVE);
-        setupMessageEvent(Collections.<OFMessage>singletonList(rr));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        swImplBase.setRole(Role.SLAVE);
-        expectLastCall().once();
-        expect(swImplBase.getNextTransactionId())
-        .andReturn(xid).anyTimes();
-        swImplBase.startDriverHandshake();
-        expectLastCall().once();
-
-        //when this flag is false, state machine will move to
-        //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
-        expect(swImplBase.isDriverHandshakeComplete())
-        .andReturn(false).once();
-
-        replay(swImplBase);
-
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-
-        assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to WAIT_INITIAL_ROLE state,
-     * then move the channel to EQUAL state based on the switch Role.
-     * This test basically test the switch with role support.
-     * Builds on moveToWaitInitialRole().
-     *
-     * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
-     * and PORT_STATUS), state machine will transit to MASTER or
-     * EQUAL state based on the switch role.
-     */
-    @Test
-    public void moveToSlaveWithHandshakeComplete()
-            throws Exception {
-
-        moveToWaitInitialRole();
-
-        int xid = 2000;
-        resetChannel();
-        replay(channel);
-
-        reset(swImplBase);
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                handler.getStateForTesting());
-
-        // build the stats reply
-        OFStatsReply sr = createDescriptionStatsReply();
-        OFMessage rr = getRoleReply(xid, Role.SLAVE);
-        setupMessageEvent(Collections.<OFMessage>singletonList(rr));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-
-        expect(controller.addActivatedEqualSwitch(1000, swImplBase))
-        .andReturn(true).once();
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        //consult the role in sw to determine the next state.
-        //in this testing case, we are testing that channel handler
-        // will move to EQUAL state when switch role is in SLAVE.
-        expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
-        swImplBase.setRole(Role.SLAVE);
-        expectLastCall().once();
-
-        expect(swImplBase.getNextTransactionId())
-        .andReturn(xid).anyTimes();
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-        swImplBase.startDriverHandshake();
-        expectLastCall().once();
-
-        //when this flag is true, don't need to move interim state
-        //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE. channel handler will
-        //move to corresponding state after consulting the role in sw
-        //This is essentially the same test as the one above,
-        //except for this line
-        expect(swImplBase.isDriverHandshakeComplete())
-        .andReturn(true).once();
-
-        replay(swImplBase);
-
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-
-        assertEquals(OFChannelHandler.ChannelState.EQUAL,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to WAIT_INITIAL_ROLE state,
-     * then to MASTERL state based on the switch Role.
-     * This test basically test the switch with role support.
-     * Builds on moveToWaitInitialRole().
-     *
-     * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
-     * and PORT_STATUS), state machine will transit to MASTER or
-     * EQUAL state based on the switch role.
-     */
-    @Test
-    public void moveToMasterWithHandshakeComplete()
-            throws Exception {
-
-        moveToWaitInitialRole();
-
-        int xid = 2000;
-        resetChannel();
-        replay(channel);
-
-        reset(swImplBase);
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                handler.getStateForTesting());
-
-        // build the stats reply
-        OFStatsReply sr = createDescriptionStatsReply();
-        OFMessage rr = getRoleReply(xid, Role.MASTER);
-        setupMessageEvent(Collections.<OFMessage>singletonList(rr));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-
-        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
-        .andReturn(true).once();
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
-        swImplBase.setRole(Role.MASTER);
-        expectLastCall().once();
-
-        expect(swImplBase.getNextTransactionId())
-        .andReturn(xid).anyTimes();
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-        swImplBase.startDriverHandshake();
-        expectLastCall().once();
-        expect(swImplBase.isDriverHandshakeComplete())
-        .andReturn(true).once();
-
-        replay(swImplBase);
-
-
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to
-     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
-     * Builds on moveToWaitSubHandshake().
-     */
-    @Test
-    public void moveToEqualViaWaitSubHandshake()
-            throws Exception {
-        moveToWaitSubHandshake();
-
-        long xid = 2000;
-        resetChannel();
-        replay(channel);
-
-        // build the stats reply
-        OFStatsReply sr = createDescriptionStatsReply();
-
-        setupMessageEvent(Collections.<OFMessage>singletonList(sr));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-
-        expect(controller.addActivatedEqualSwitch(1000, swImplBase))
-        .andReturn(true).once();
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
-        expect(swImplBase.getNextTransactionId())
-        .andReturn((int) xid).anyTimes();
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-
-        swImplBase.processDriverHandshakeMessage(sr);
-        expectLastCall().once();
-        expect(swImplBase.isDriverHandshakeComplete())
-        .andReturn(true).once();
-
-        replay(swImplBase);
-
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-
-        assertEquals(OFChannelHandler.ChannelState.EQUAL,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to
-     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
-     * Builds on moveToWaitSubHandshake().
-     */
-    @Test
-    public void moveToMasterViaWaitSubHandshake()
-            throws Exception {
-        moveToWaitSubHandshake();
-
-        long xid = 2000;
-        resetChannel();
-        replay(channel);
-
-        // In this state, any messages except echo request, port status and
-        // error go to the switch sub driver handshake. Once the switch reports
-        // that its sub driver handshake is complete (#isDriverHandshakeComplete
-        // return true) then the channel handle consults the switch role and
-        // moves the state machine to the appropriate state (MASTER or EQUALS).
-        // In this test we expect the state machine to end up in MASTER state.
-        OFStatsReply sr = createDescriptionStatsReply();
-
-        setupMessageEvent(Collections.<OFMessage>singletonList(sr));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
-        .andReturn(true).once();
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
-        expect(swImplBase.getNextTransactionId())
-        .andReturn((int) xid).anyTimes();
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-
-        swImplBase.processDriverHandshakeMessage(sr);
-        expectLastCall().once();
-        expect(swImplBase.isDriverHandshakeComplete())
-        .andReturn(true).once();
-
-        replay(swImplBase);
-
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-        verify(controller);
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Test the behavior in WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
-     * ECHO_REQUEST message received case.
-     */
-    @Test
-    public void testWaitSwitchDriverSubhandshake() throws Exception {
-        moveToWaitSubHandshake();
-
-        long xid = 2000;
-        resetChannel();
-        channel.write(capture(writeCapture));
-        expectLastCall().andReturn(null).atLeastOnce();
-        replay(channel);
-
-        OFMessage er = buildOFMessage(OFType.ECHO_REQUEST);
-
-        setupMessageEvent(Collections.<OFMessage>singletonList(er));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFMessageFactory10()).andReturn(factory10);
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        expect(swImplBase.getNextTransactionId())
-        .andReturn((int) xid).anyTimes();
-
-        replay(swImplBase);
-
-        handler.messageReceived(ctx, messageEvent);
-
-        List<OFMessage> msgs = getMessagesFromCapture();
-        assertEquals(1, msgs.size());
-        assertEquals(OFType.ECHO_REPLY, msgs.get(0).getType());
-        verifyUniqueXids(msgs);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Helper.
-     * Verify that the given OFMessage is a correct Nicira RoleRequest message.
-     */
-    private void verifyNiciraMessage(OFExperimenter ofMessage) {
-
-        int vendor = (int) ofMessage.getExperimenter();
-        assertEquals(vendor, 0x2320); // magic number representing nicira
-    }
-
-    /**
-     * Setup the mock switch and write capture for a role request, set the
-     * role and verify mocks.
-     * @param supportsNxRole whether the switch supports role request messages
-     * to setup the attribute. This must be null (don't yet know if roles
-     * supported: send to check) or true.
-     * @param xid The xid to use in the role request
-     * @param role The role to send
-     * @throws IOException
-     */
-    private void setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole,
-            int xid,
-            Role role) throws IOException {
-
-        RoleRecvStatus expectation = RoleRecvStatus.MATCHED_SET_ROLE;
-
-        expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
-        .andReturn(supportsNxRole).atLeastOnce();
-
-        if (supportsNxRole != null && supportsNxRole) {
-            expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
-            swImplBase.write(capture(writeCapture));
-            expectLastCall().anyTimes();
-        }
-        replay(swImplBase);
-
-        handler.sendRoleRequest(role, expectation);
-
-        if (supportsNxRole != null && supportsNxRole) {
-            List<OFMessage> msgs = getMessagesFromCapture();
-            assertEquals(1, msgs.size());
-            verifyNiciraMessage((OFExperimenter) msgs.get(0));
-        }
-    }
-
-    /**
-     * Setup the mock switch for a role change request where the switch
-     * does not support roles.
-     *
-     * Needs to verify and reset the controller since we need to set
-     * an expectation
-     */
-    private void setupSwitchRoleChangeUnsupported(int xid,
-            Role role) {
-        boolean supportsNxRole = false;
-        RoleRecvStatus expectation = RoleRecvStatus.NO_REPLY;
-        reset(swImplBase);
-        expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
-        .andReturn(supportsNxRole).atLeastOnce();
-        // TODO: hmmm. While it's not incorrect that we set the attribute
-        // again it looks odd. Maybe change
-        swImplBase.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
-        expectLastCall().anyTimes();
-
-        replay(swImplBase);
-
-        handler.sendRoleRequest(role, expectation);
-
-        verify(swImplBase);
-    }
-
-    /*
-     * Return a Nicira RoleReply message for the given role.
-     */
-    private OFMessage getRoleReply(long xid, Role role) {
-
-        OFNiciraControllerRole nr = null;
-
-        switch(role) {
-        case MASTER:
-            nr = OFNiciraControllerRole.ROLE_MASTER;
-            break;
-        case EQUAL:
-            nr = OFNiciraControllerRole.ROLE_SLAVE;
-            break;
-        case SLAVE:
-            nr = OFNiciraControllerRole.ROLE_SLAVE;
-            break;
-        default: //handled below
-        }
-        OFMessage m = factory10.buildNiciraControllerRoleReply()
-                .setRole(nr)
-                .setXid(xid)
-                .build();
-        return m;
-    }
-
-    /**
-     * Move the channel from scratch to MASTER state.
-     * Builds on moveToWaitInitialRole().
-     * adds testing for WAIT_INITAL_ROLE state.
-     *
-     * This method tests the case that the switch does NOT support roles.
-     * In ONOS if the switch-driver says that nicira-role messages are not
-     * supported, then ONOS does NOT send role-request messages
-     * (see handleUnsentRoleMessage())
-     */
-    @Test
-    public void testInitialMoveToMasterNoRole() throws Exception {
-        int xid = 43;
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-
-        moveToWaitInitialRole();
-        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                handler.getStateForTesting());
-
-        OFStatsReply sr = createDescriptionStatsReply();
-
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-
-        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
-        .andReturn(true).once();
-        replay(controller);
-
-        reset(swImplBase);
-        swImplBase.setRole(Role.MASTER);
-        expectLastCall().once();
-        swImplBase.startDriverHandshake();
-        expectLastCall().once();
-        expect(swImplBase.isDriverHandshakeComplete())
-        .andReturn(true).once();
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
-
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(false, xid, Role.MASTER);
-
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel from scratch to WAIT_INITIAL_ROLE state.
-     * Builds on moveToWaitInitialRole().
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * We let the initial role request time out. Role support should be
-     * disabled but the switch should be activated.
-     */
-    /* TBD
-        @Test
-        public void testInitialMoveToMasterTimeout() throws Exception {
-            int timeout = 50;
-            handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
-            int xid = 4343;
-
-            // first, move us to WAIT_INITIAL_ROLE_STATE
-
-            moveToWaitInitialRole();
-            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                    handler.getStateForTesting());
-
-            // prepare mocks and inject the role reply message
-            reset(swImplBase);
-            // Set the role
-            swImplBase.setRole(Role.MASTER);
-            expectLastCall().once();
-            swImplBase.startDriverHandshake();
-            expectLastCall().once();
-            expect(swImplBase.isDriverHandshakeComplete())
-            .andReturn(false).once();
-            if (ofVersion == OFVersion.OF_10) {
-                expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
-                 .andReturn(true).once();
-
-                swImplBase.write(capture(writeCapture),
-                        EasyMock.<FloodlightContext>anyObject());
-                expectLastCall().anyTimes();
-             }
-            expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
-
-            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                    handler.getStateForTesting());
-
-            // Set the role
-            setupSwitchSendRoleRequestAndVerify(null, xid, Role.MASTER);
-            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                    handler.getStateForTesting());
-
-            OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
-
-            setupMessageEvent(Collections.<OFMessage>singletonList(m));
-
-            Thread.sleep(timeout+5);
-
-            verify(controller);
-            reset(controller);
-
-            expect(controller.addActivatedMasterSwitch(1000, swImplBase))
-            .andReturn(true).once();
-            controller.flushAll();
-            expectLastCall().once();
-
-            replay(controller);
-
-            handler.messageReceived(ctx, messageEvent);
-
-            assertEquals(OFChannelHandler.ChannelState.MASTER,
-                    handler.getStateForTesting());
-
-        }
-
-     */
-    /**
-     * Move the channel from scratch to SLAVE state.
-     * Builds on doMoveToWaitInitialRole().
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * This method tests the case that the switch does NOT support roles.
-     * The channel handler still needs to send the initial request to find
-     * out that whether the switch supports roles.
-     *
-     */
-    @Test
-    public void testInitialMoveToSlaveNoRole() throws Exception {
-        int xid = 44;
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                handler.getStateForTesting());
-
-        reset(swImplBase);
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(false, xid, Role.SLAVE);
-        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                handler.getStateForTesting());
-
-    }
-
-    /**
-     * Move the channel from scratch to SLAVE state.
-     * Builds on doMoveToWaitInitialRole().
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * We let the initial role request time out. The switch should be
-     * disconnected
-     */
-    /* TBD
-        @Test
-        public void testInitialMoveToSlaveTimeout() throws Exception {
-            int timeout = 50;
-            handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
-            int xid = 4444;
-
-            // first, move us to WAIT_INITIAL_ROLE_STATE
-            moveToWaitInitialRole();
-            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                    handler.getStateForTesting());
-
-            // Set the role
-            setupSwitchSendRoleRequestAndVerify(null, xid, Role.SLAVE);
-            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                    handler.getStateForTesting());
-
-            // prepare mocks and inject the role reply message
-            reset(sw);
-            sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
-            expectLastCall().once();
-            sw.setRole(Role.SLAVE);
-            expectLastCall().once();
-            sw.disconnectSwitch(); // Make sure we disconnect
-            expectLastCall().once();
-            replay(sw);
-
-            OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
-
-            Thread.sleep(timeout+5);
-
-            sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
-        }
-
-     */
-    /**
-     * Move channel from scratch to WAIT_INITIAL_STATE, then MASTER,
-     * then SLAVE for cases where the switch does not support roles.
-     * I.e., the final SLAVE transition should disconnect the switch.
-     */
-    @Test
-    public void testNoRoleInitialToMasterToSlave() throws Exception {
-        int xid = 46;
-        reset(swImplBase);
-        replay(swImplBase);
-
-        reset(controller);
-        replay(controller);
-
-        // First, lets move the state to MASTER without role support
-        testInitialMoveToMasterNoRole();
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-
-        // try to set master role again. should be a no-op
-        setupSwitchRoleChangeUnsupported(xid, Role.MASTER);
-
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-
-        setupSwitchRoleChangeUnsupported(xid, Role.SLAVE);
-        //switch does not support role message. there is no role set
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-
-    }
-
-    /**
-     * Move the channel to MASTER state.
-     * Expects that the channel is in MASTER or SLAVE state.
-     *
-     */
-    public void changeRoleToMasterWithRequest() throws Exception {
-        int xid = 4242;
-
-        assertTrue("This method can only be called when handler is in " +
-                "MASTER or SLAVE role", handler.isHandshakeComplete());
-
-        reset(swImplBase);
-        reset(controller);
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
-
-        // prepare mocks and inject the role reply message
-
-        reset(controller);
-        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
-        .andReturn(true).once();
-        OFMessage reply = getRoleReply(xid, Role.MASTER);
-
-        // sendMessageToHandler will verify and rest controller mock
-
-        OFStatsReply sr = createDescriptionStatsReply();
-        setupMessageEvent(Collections.<OFMessage>singletonList(reply));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-        controller.transitionToMasterSwitch(1000);
-        expectLastCall().once();
-
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        expect(swImplBase.getRole()).andReturn(Role.EQUAL).atLeastOnce();
-        expect(swImplBase.getNextTransactionId())
-        .andReturn(xid).anyTimes();
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-
-        swImplBase.setRole(Role.MASTER);
-        expectLastCall().once();
-        replay(swImplBase);
-
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-    }
-
-    /**
-     * Move the channel to SLAVE state.
-     * Expects that the channel is in MASTER or SLAVE state.
-     *
-     */
-    public void changeRoleToSlaveWithRequest() throws Exception {
-        int xid = 2323;
-
-        assertTrue("This method can only be called when handler is in " +
-                "MASTER or SLAVE role", handler.isHandshakeComplete());
-
-        // Set the role
-        reset(controller);
-        reset(swImplBase);
-
-        swImplBase.write(capture(writeCapture));
-        expectLastCall().anyTimes();
-
-        expect(swImplBase.getNextTransactionId())
-        .andReturn(xid).anyTimes();
-
-
-        if (ofVersion == OFVersion.OF_10) {
-            expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
-            .andReturn(true).once();
-
-            swImplBase.write(capture(writeCapture));
-            expectLastCall().anyTimes();
-        }
-        replay(swImplBase);
-
-        handler.sendRoleRequest(Role.SLAVE, RoleRecvStatus.MATCHED_SET_ROLE);
-
-        List<OFMessage> msgs = getMessagesFromCapture();
-        assertEquals(1, msgs.size());
-        verifyNiciraMessage((OFExperimenter) msgs.get(0));
-
-
-        OFMessage reply = getRoleReply(xid, Role.SLAVE);
-        OFStatsReply sr = createDescriptionStatsReply();
-        setupMessageEvent(Collections.<OFMessage>singletonList(reply));
-
-        // mock controller
-        reset(controller);
-        reset(swImplBase);
-
-        controller.transitionToEqualSwitch(1000);
-        expectLastCall().once();
-        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
-        .andReturn(swImplBase).anyTimes();
-
-        expect(controller.getDebugCounter())
-        .andReturn(debugCounterService).anyTimes();
-
-        replay(controller);
-
-        expect(swImplBase.getStringId())
-        .andReturn(null).anyTimes();
-        expect(swImplBase.getRole()).andReturn(Role.MASTER).atLeastOnce();
-        expect(swImplBase.getNextTransactionId())
-        .andReturn(xid).anyTimes();
-
-        // prepare mocks and inject the role reply message
-        swImplBase.setRole(Role.SLAVE);
-        expectLastCall().once();
-        expect(swImplBase.getId())
-        .andReturn(1000L).once();
-        replay(swImplBase);
-
-        handler.messageReceived(ctx, messageEvent);
-
-        assertEquals(OFChannelHandler.ChannelState.EQUAL,
-                handler.getStateForTesting());
-    }
-
-    @Test
-    public void testMultiRoleChange1() throws Exception {
-        moveToMasterWithHandshakeComplete();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-    }
-
-    @Test
-    public void testMultiRoleChange2() throws Exception {
-        moveToSlaveWithHandshakeComplete();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-    }
-
-    /**
-     * Start from scratch and reply with an unexpected error to the role
-     * change request.
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     */
-    /* TBD
-        @Test
-        public void testInitialRoleChangeOtherError() throws Exception {
-            int xid = 4343;
-            // first, move us to WAIT_INITIAL_ROLE_STATE
-            moveToWaitInitialRole();
-            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                    handler.getStateForTesting());
-
-            reset(swImplBase);
-            // Set the role
-            setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
-            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
-                    handler.getStateForTesting());
-
-
-            // FIXME: shouldn't use ordinal(), but OFError is broken
-
-            OFMessage err = factory.errorMsgs().buildBadActionErrorMsg()
-                    .setCode(OFBadActionCode.BAD_LEN)
-                    .setXid(2000)
-                    .build();
-            verify(swImplBase);
-            reset(swImplBase);
-            replay(swImplBase);
-            sendMessageToHandlerWithControllerReset(Collections.singletonList(err));
-
-            verifyExceptionCaptured(SwitchStateException.class);
-        }
-     */
-    /**
-     * Test dispatch of messages while in MASTER role.
-     */
-    @Test
-    public void testMessageDispatchMaster() throws Exception {
-
-        moveToMasterWithHandshakeComplete();
-
-        // Send packet in. expect dispatch
-        OFPacketIn pi = (OFPacketIn)
-                buildOFMessage(OFType.PACKET_IN);
-        setupMessageEvent(Collections.<OFMessage>singletonList(pi));
-
-        reset(swImplBase);
-        swImplBase.handleMessage(pi);
-        expectLastCall().once();
-        replay(swImplBase);
-        // send the description stats reply
-        handler.messageReceived(ctx, messageEvent);
-
-        assertEquals(OFChannelHandler.ChannelState.MASTER,
-                handler.getStateForTesting());
-
-        verify(controller);
-        // TODO: many more to go
-    }
-
-    /**
-     * Test port status message handling while MASTER.
-     *
-     */
-    /* Patrick: TBD
-        @Test
-        public void testPortStatusMessageMaster() throws Exception {
-            long dpid = featuresReply.getDatapathId().getLong();
-            testInitialMoveToMasterWithRole();
-            List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
-            // A dummy port.
-            OFPortDesc p = factory.buildPortDesc()
-                        .setName("Eth1")
-                        .setPortNo(OFPort.ofInt(1))
-                        .build();
-            ports.add(p);
-
-            p.setName("Port1");
-            p.setPortNumber((short)1);
-
-            OFPortStatus ps = (OFPortStatus)buildOFMessage(OFType.PORT_STATUS);
-            ps.setDesc(p);
-
-            // The events we expect sw.handlePortStatus to return
-            // We'll just use the same list for all valid OFPortReasons and add
-            // arbitrary events for arbitrary ports that are not necessarily
-            // related to the port status message. Our goal
-            // here is not to return the correct set of events but the make sure
-            // that a) sw.handlePortStatus is called
-            //      b) the list of events sw.handlePortStatus returns is sent
-            //         as IOFSwitchListener notifications.
-            OrderedCollection<PortChangeEvent> events =
-                    new LinkedHashSetWrapper<PortChangeEvent>();
-            ImmutablePort p1 = ImmutablePort.create("eth1", (short)1);
-            ImmutablePort p2 = ImmutablePort.create("eth2", (short)2);
-            ImmutablePort p3 = ImmutablePort.create("eth3", (short)3);
-            ImmutablePort p4 = ImmutablePort.create("eth4", (short)4);
-            ImmutablePort p5 = ImmutablePort.create("eth5", (short)5);
-            events.add(new PortChangeEvent(p1, PortChangeType.ADD));
-            events.add(new PortChangeEvent(p2, PortChangeType.DELETE));
-            events.add(new PortChangeEvent(p3, PortChangeType.UP));
-            events.add(new PortChangeEvent(p4, PortChangeType.DOWN));
-            events.add(new PortChangeEvent(p5, PortChangeType.OTHER_UPDATE));
-
-
-            for (OFPortReason reason: OFPortReason.values()) {
-                ps.setReason(reason.getReasonCode());
-
-                reset(sw);
-                expect(sw.getId()).andReturn(dpid).anyTimes();
-
-                expect(sw.processOFPortStatus(ps)).andReturn(events).once();
-                replay(sw);
-
-                reset(controller);
-                controller.notifyPortChanged(sw, p1, PortChangeType.ADD);
-                controller.notifyPortChanged(sw, p2, PortChangeType.DELETE);
-                controller.notifyPortChanged(sw, p3, PortChangeType.UP);
-                controller.notifyPortChanged(sw, p4, PortChangeType.DOWN);
-                controller.notifyPortChanged(sw, p5, PortChangeType.OTHER_UPDATE);
-                sendMessageToHandlerNoControllerReset(
-                        Collections.<OFMessage>singletonList(ps));
-                verify(sw);
-                verify(controller);
-            }
-        }
-
-     */
-    /**
-     * Build an OF message.
-     * @throws IOException
-     */
-    private OFMessage buildOFMessage(OFType t) throws IOException {
-        OFMessage m = null;
-        switch (t) {
-
-        case HELLO:
-            // The OF protocol requires us to start things off by sending the highest
-            // version of the protocol supported.
-
-            // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04)
-            // see Sec. 7.5.1 of the OF1.3.4 spec
-            if (ofVersion == OFVersion.OF_13) {
-                U32 bitmap = U32.ofRaw(0x00000012);
-                OFHelloElem hem = factory13.buildHelloElemVersionbitmap()
-                    .setBitmaps(Collections.singletonList(bitmap))
-                    .build();
-                m = factory13.buildHello()
-                        .setXid(2000)
-                        .setElements(Collections.singletonList(hem))
-                        .build();
-            } else {
-                m = factory10.buildHello()
-                    .setXid(2000)
-                    .build();
-            }
-            break;
-        case FEATURES_REQUEST:
-            m = factory.buildFeaturesRequest()
-            .setXid(2000)
-            .build();
-            break;
-        case FEATURES_REPLY:
-
-            m = factory.buildFeaturesReply()
-            .setDatapathId(DatapathId.of(1000L))
-            .setXid(2000)
-            .build();
-            break;
-        case SET_CONFIG:
-            m = factory.buildSetConfig()
-            .setMissSendLen((short) 0xffff)
-            .setXid(2000)
-            .build();
-            break;
-        case BARRIER_REQUEST:
-            m = factory.buildBarrierRequest()
-            .setXid(2000)
-            .build();
-            break;
-        case GET_CONFIG_REQUEST:
-            m = factory.buildGetConfigRequest()
-            .setXid(2000)
-            .build();
-            break;
-        case GET_CONFIG_REPLY:
-            m = factory.buildGetConfigReply()
-            .setMissSendLen((short) 0xffff)
-            .setXid(2000)
-            .build();
-            break;
-        case STATS_REQUEST:
-            break;
-        case STATS_REPLY:
-            m = factory.buildDescStatsReply()
-            .setDpDesc("Datapath Description")
-            .setHwDesc("Hardware Secription")
-            .setMfrDesc("Manufacturer Desctiption")
-            .setSerialNum("Serial Number")
-            .setSwDesc("Software Desription")
-            .build();
-            break;
-        case ECHO_REQUEST:
-            m = factory.buildEchoRequest()
-            .setXid(2000)
-            .build();
-            break;
-        case FLOW_REMOVED:
-            break;
-
-        case PACKET_IN:
-            m = factory.buildPacketIn()
-            .setReason(OFPacketInReason.NO_MATCH)
-            .setTotalLen(1500)
-            .setXid(2000)
-            .build();
-            break;
-        case PORT_STATUS:
-            m = factory.buildPortStatus()
-            .setXid(2000)
-            .build();
-            break;
-
-        default:
-            m = factory.buildFeaturesRequest()
-            .setXid(2000)
-            .build();
-            break;
-        }
-
-        return (m);
-    }
-}