refactored OF switch into driver and frontend
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
deleted file mode 100644
index 534daa0..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/AbstractOpenFlowSwitch.java
+++ /dev/null
@@ -1,308 +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 java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-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.OFDescStatsReply;
-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.OFPortDesc;
-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);
-
-    protected Channel channel;
-    protected boolean startDriverHandshakeCalled = false;
-
-    private boolean connected;
-    private Dpid dpid;
-    private OpenFlowSwitchAgent agent;
-    private AtomicInteger xidCounter = new AtomicInteger(0);
-
-    private OFVersion ofVersion;
-
-    protected OFPortDescStatsReply ports;
-
-    protected boolean tableFull;
-
-    private final RoleManager roleMan = new RoleManager(this);
-
-    protected RoleState role;
-
-    protected OFFeaturesReply features;
-
-    protected AbstractOpenFlowSwitch(Dpid dp) {
-        this.dpid = dp;
-    }
-
-    //************************
-    // 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 sendMsg(OFMessage m);
-
-    /**
-     * Writes to the OFMessage list to the output stream.
-     *
-     * @param msgs the messages to be written
-     */
-    public void write(List<OFMessage> msgs) {
-        this.channel.write(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 void setFeaturesReply(OFFeaturesReply featuresReply) {
-        this.features = 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 RoleState getRole() {
-        return role;
-    };
-
-    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 {
-            if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
-                this.role = 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 r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
-        if (r == 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(r, null, m.getXid()));
-        if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
-            if (r == RoleState.MASTER) {
-                this.transitionToMasterSwitch();
-            } else if (r == RoleState.EQUAL ||
-                    r == 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;
-    }
-
-    public void setSwitchDescription(OFDescStatsReply desc) {
-        // TODO Auto-generated method stub
-    }
-
-    protected int getNextTransactionId() {
-        return this.xidCounter.getAndIncrement();
-    }
-
-    protected List<OFPortDesc> getPorts() {
-        return Collections.unmodifiableList(ports.getEntries());
-    }
-
-}
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 b88a9ec..ab9315f 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
@@ -30,9 +30,10 @@
 import org.jboss.netty.channel.group.DefaultChannelGroup;
 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
 import org.onlab.onos.of.controller.Dpid;
+import org.onlab.onos.of.controller.driver.OpenFlowAgent;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
 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.onlab.onos.of.drivers.DriverManager;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFFactories;
@@ -74,7 +75,7 @@
 
     // Flag to always flush flow table on switch reconnect (HA or otherwise)
     protected boolean alwaysClearFlowsOnSwAdd = false;
-    private OpenFlowSwitchAgent agent;
+    private OpenFlowAgent agent;
 
     // Perf. related configuration
     protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
@@ -120,17 +121,17 @@
      * Tell controller that we're ready to accept switches loop.
      */
     @LogMessageDocs({
-            @LogMessageDoc(message = "Listening for switch connections on {address}",
-                    explanation = "The controller is ready and listening for new" +
-                            " switch connections"),
-            @LogMessageDoc(message = "Storage exception in controller " +
-                    "updates loop; terminating process",
-                    explanation = ERROR_DATABASE,
-                    recommendation = LogMessageDoc.CHECK_CONTROLLER),
-            @LogMessageDoc(level = "ERROR",
-                    message = "Exception in controller updates loop",
-                    explanation = "Failed to dispatch controller event",
-                    recommendation = LogMessageDoc.GENERIC_ACTION)
+        @LogMessageDoc(message = "Listening for switch connections on {address}",
+                explanation = "The controller is ready and listening for new" +
+                " switch connections"),
+                @LogMessageDoc(message = "Storage exception in controller " +
+                        "updates loop; terminating process",
+                        explanation = ERROR_DATABASE,
+                        recommendation = LogMessageDoc.CHECK_CONTROLLER),
+                        @LogMessageDoc(level = "ERROR",
+                        message = "Exception in controller updates loop",
+                        explanation = "Failed to dispatch controller event",
+                        recommendation = LogMessageDoc.GENERIC_ACTION)
     })
     public void run() {
 
@@ -221,15 +222,16 @@
      * @param desc
      * @return switch instance
      */
-    protected AbstractOpenFlowSwitch getOFSwitchInstance(long dpid,
+    protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
             OFDescStatsReply desc, OFVersion ofv) {
-        AbstractOpenFlowSwitch sw = DriverManager.getOFSwitchImpl(new Dpid(dpid),
+        OpenFlowSwitchDriver sw = DriverManager.getSwitch(new Dpid(dpid),
                 desc, ofv);
         sw.setAgent(agent);
+        sw.setRoleHandler(new RoleManager(sw));
         return sw;
     }
 
-    public void start(OpenFlowSwitchAgent ag) {
+    public void start(OpenFlowAgent ag) {
         log.info("Initialising OpenFlow Lib and IO");
         this.agent = ag;
         this.init(new HashMap<String, String>());
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
index 4b2f7c3..035c4ca 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/IOFSwitchManager.java
@@ -1,5 +1,6 @@
 package org.onlab.onos.of.controller.impl.internal;
 
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
 import org.projectfloodlight.openflow.protocol.OFVersion;
 
 
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 23bc994..768362f 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
@@ -18,6 +18,8 @@
 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.driver.OpenFlowSwitchDriver;
+import org.onlab.onos.of.controller.driver.SwitchStateException;
 import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
 import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
@@ -66,7 +68,7 @@
 class OFChannelHandler extends IdleStateAwareChannelHandler {
     private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
     private final Controller controller;
-    private AbstractOpenFlowSwitch sw;
+    private OpenFlowSwitchDriver sw;
     private long thisdpid; // channelHandler cached value of connected switch id
     private Channel channel;
     // State needs to be volatile because the HandshakeTimeoutHandler
@@ -413,7 +415,7 @@
                 OFDescStatsReply drep = (OFDescStatsReply) m;
                 // Here is where we differentiate between different kinds of switches
                 h.sw = h.controller.getOFSwitchInstance(h.thisdpid, drep, h.ofVersion);
-                boolean success = h.sw.addConnectedSwitch();
+                boolean success = h.sw.connectSwitch();
                 if (!success) {
                     disconnectDuplicate(h);
                     return;
@@ -431,7 +433,7 @@
                 //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.sw.addActivatedEqualSwitch();
+                h.sw.activateEqualSwitch();
                 //h.setSwitchRole(RoleState.EQUAL);
                 h.setSwitchRole(RoleState.MASTER);
                 h.sw.startDriverHandshake();
@@ -489,8 +491,8 @@
                         }
                     }
                 } else {
-                    if (m.getType() == OFType.EXPERIMENTER && 
-                            ((OFExperimenter) m).getExperimenter() == 
+                    if (m.getType() == OFType.EXPERIMENTER &&
+                            ((OFExperimenter) m).getExperimenter() ==
                             RoleManager.NICIRA_EXPERIMENTER) {
                         h.sw.handleNiciraRole(m);
                     } else {
@@ -848,8 +850,8 @@
                 processOFQueueGetConfigReply(h, (OFQueueGetConfigReply) m);
                 break;
             case STATS_REPLY: // multipart_reply in 1.3
-            processOFStatisticsReply(h, (OFStatsReply) m);
-            break;
+                processOFStatisticsReply(h, (OFStatsReply) m);
+                break;
             case EXPERIMENTER:
                 processOFExperimenter(h, (OFExperimenter) m);
                 break;
@@ -916,12 +918,12 @@
             }
             OFFactory factory = (h.ofVersion == OFVersion.OF_13) ?
                     h.controller.getOFMessageFactory13() : h.controller.getOFMessageFactory10();
-            OFEchoReply reply = factory
-                    .buildEchoReply()
-                    .setXid(m.getXid())
-                    .setData(m.getData())
-                    .build();
-            h.channel.write(Collections.singletonList(reply));
+                    OFEchoReply reply = factory
+                            .buildEchoReply()
+                            .setXid(m.getXid())
+                            .setData(m.getData())
+                            .build();
+                    h.channel.write(Collections.singletonList(reply));
         }
 
         void processOFEchoReply(OFChannelHandler h, OFEchoReply m)
@@ -1044,41 +1046,41 @@
                 message = "Disconnecting switch {switch} due to read timeout",
                 explanation = "The connected switch has failed to send any "
                         + "messages or respond to echo requests",
-                recommendation = LogMessageDoc.CHECK_SWITCH),
+                        recommendation = LogMessageDoc.CHECK_SWITCH),
                         @LogMessageDoc(level = "ERROR",
-                message = "Disconnecting switch {switch}: failed to "
-                        + "complete handshake",
-                explanation = "The switch did not respond correctly "
-                        + "to handshake messages",
-                recommendation = LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level = "ERROR",
-                message = "Disconnecting switch {switch} due to IO Error: {}",
-                explanation = "There was an error communicating with the switch",
-                recommendation = LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level = "ERROR",
-                message = "Disconnecting switch {switch} due to switch "
-                        + "state error: {error}",
-                explanation = "The switch sent an unexpected message",
-                recommendation = LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level = "ERROR",
-                message = "Disconnecting switch {switch} due to "
-                          + "message parse failure",
-                explanation = "Could not parse a message from the switch",
-                recommendation = LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level = "ERROR",
-                message = "Terminating controller due to storage exception",
-                explanation = Controller.ERROR_DATABASE,
-                recommendation = LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level = "ERROR",
-                message = "Could not process message: queue full",
-                explanation = "OpenFlow messages are arriving faster than "
-                            + "the controller can process them.",
-                recommendation = LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level = "ERROR",
-                message = "Error while processing message "
-                        + "from switch {switch} {cause}",
-                explanation = "An error occurred processing the switch message",
-                recommendation = LogMessageDoc.GENERIC_ACTION)
+                        message = "Disconnecting switch {switch}: failed to "
+                                + "complete handshake",
+                                explanation = "The switch did not respond correctly "
+                                        + "to handshake messages",
+                                        recommendation = LogMessageDoc.CHECK_SWITCH),
+                                        @LogMessageDoc(level = "ERROR",
+                                        message = "Disconnecting switch {switch} due to IO Error: {}",
+                                        explanation = "There was an error communicating with the switch",
+                                        recommendation = LogMessageDoc.CHECK_SWITCH),
+                                        @LogMessageDoc(level = "ERROR",
+                                        message = "Disconnecting switch {switch} due to switch "
+                                                + "state error: {error}",
+                                                explanation = "The switch sent an unexpected message",
+                                                recommendation = LogMessageDoc.CHECK_SWITCH),
+                                                @LogMessageDoc(level = "ERROR",
+                                                message = "Disconnecting switch {switch} due to "
+                                                        + "message parse failure",
+                                                        explanation = "Could not parse a message from the switch",
+                                                        recommendation = LogMessageDoc.CHECK_SWITCH),
+                                                        @LogMessageDoc(level = "ERROR",
+                                                        message = "Terminating controller due to storage exception",
+                                                        explanation = Controller.ERROR_DATABASE,
+                                                        recommendation = LogMessageDoc.CHECK_CONTROLLER),
+                                                        @LogMessageDoc(level = "ERROR",
+                                                        message = "Could not process message: queue full",
+                                                        explanation = "OpenFlow messages are arriving faster than "
+                                                                + "the controller can process them.",
+                                                                recommendation = LogMessageDoc.CHECK_CONTROLLER),
+                                                                @LogMessageDoc(level = "ERROR",
+                                                                message = "Error while processing message "
+                                                                        + "from switch {switch} {cause}",
+                                                                        explanation = "An error occurred processing the switch message",
+                                                                        recommendation = LogMessageDoc.GENERIC_ACTION)
     })
     public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
             throws Exception {
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
index f846e65..b7ba4c7 100644
--- 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
@@ -15,8 +15,9 @@
 import org.onlab.onos.of.controller.OpenFlowSwitchListener;
 import org.onlab.onos.of.controller.PacketListener;
 import org.onlab.onos.of.controller.RoleState;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.OpenFlowAgent;
 import org.projectfloodlight.openflow.protocol.OFMessage;
-import org.projectfloodlight.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -27,12 +28,12 @@
     private static final Logger log =
             LoggerFactory.getLogger(OpenFlowControllerImpl.class);
 
-    protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches =
-            new ConcurrentHashMap<Long, OpenFlowSwitch>();
-    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches =
-            new ConcurrentHashMap<Long, OpenFlowSwitch>();
-    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches =
-            new ConcurrentHashMap<Long, OpenFlowSwitch>();
+    protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
+            new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
+    protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
+            new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
+    protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
+            new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
 
     protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
     protected ArrayList<OpenFlowSwitchListener> ofEventListener =
@@ -118,12 +119,13 @@
         ((AbstractOpenFlowSwitch) getSwitch(dpid)).setRole(role);
     }
 
-    public class OpenFlowSwitchAgent {
+    public class OpenFlowSwitchAgent implements OpenFlowAgent {
 
         private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
-        private Lock switchLock = new ReentrantLock();
+        private final Lock switchLock = new ReentrantLock();
 
-        public boolean addConnectedSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+        @Override
+        public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
             if (connectedSwitches.get(dpid) != null) {
                 log.error("Trying to add connectedSwitch but found a previous "
                         + "value for dpid: {}", dpid);
@@ -132,17 +134,18 @@
                 log.error("Added switch {}", dpid);
                 connectedSwitches.put(dpid, sw);
                 for (OpenFlowSwitchListener l : ofEventListener) {
-                    l.switchAdded(new Dpid(dpid));
+                    l.switchAdded(dpid);
                 }
                 return true;
             }
         }
 
-        private boolean validActivation(long dpid) {
+        @Override
+        public boolean validActivation(Dpid dpid) {
             if (connectedSwitches.get(dpid) == null) {
                 log.error("Trying to activate switch but is not in "
                         + "connected switches: dpid {}. Aborting ..",
-                        HexString.toHexString(dpid));
+                        dpid);
                 return false;
             }
             if (activeMasterSwitches.get(dpid) != null ||
@@ -150,18 +153,17 @@
                 log.error("Trying to activate switch but it is already "
                         + "activated: dpid {}. Found in activeMaster: {} "
                         + "Found in activeEqual: {}. Aborting ..", new Object[] {
-                                HexString.toHexString(dpid),
+                                dpid,
                                 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
-                                (activeEqualSwitches.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) {
+
+        @Override
+        public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
             switchLock.lock();
             try {
                 if (!validActivation(dpid)) {
@@ -172,31 +174,25 @@
             } finally {
                 switchLock.unlock();
             }
-    }
+        }
 
-        /**
-         * Called when a switch is activated, with this controller's role as EQUAL.
-         */
-        protected boolean addActivatedEqualSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+        @Override
+        public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
             switchLock.lock();
             try {
-                    if (!validActivation(dpid)) {
-                        return false;
-                    }
-                    activeEqualSwitches.put(dpid, sw);
-                    log.info("Added Activated EQUAL Switch {}", dpid);
-                    return true;
+                if (!validActivation(dpid)) {
+                    return false;
+                }
+                activeEqualSwitches.put(dpid, sw);
+                log.info("Added Activated EQUAL Switch {}", dpid);
+                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) {
+        @Override
+        public void transitionToMasterSwitch(Dpid dpid) {
             switchLock.lock();
             try {
                 if (activeMasterSwitches.containsKey(dpid)) {
@@ -215,12 +211,8 @@
         }
 
 
-        /**
-         * 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) {
+        @Override
+        public void transitionToEqualSwitch(Dpid dpid) {
             switchLock.lock();
             try {
                 if (activeEqualSwitches.containsKey(dpid)) {
@@ -239,22 +231,19 @@
 
         }
 
-        /**
-         * 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) {
+        @Override
+        public void removeConnectedSwitch(Dpid 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));
+                l.switchRemoved(dpid);
             }
         }
 
+        @Override
         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
index 99e9173..235eb61 100644
--- 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
@@ -4,6 +4,11 @@
 import java.util.Collections;
 
 import org.onlab.onos.of.controller.RoleState;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
+import org.onlab.onos.of.controller.driver.RoleHandler;
+import org.onlab.onos.of.controller.driver.RoleRecvStatus;
+import org.onlab.onos.of.controller.driver.RoleReplyInfo;
+import org.onlab.onos.of.controller.driver.SwitchStateException;
 import org.projectfloodlight.openflow.protocol.OFControllerRole;
 import org.projectfloodlight.openflow.protocol.OFErrorMsg;
 import org.projectfloodlight.openflow.protocol.OFErrorType;
@@ -35,7 +40,7 @@
  * a new request is submitted before the timeout triggers. If necessary
  * we could work around that though.
  */
-class RoleManager {
+class RoleManager implements RoleHandler {
     protected static final long NICIRA_EXPERIMENTER = 0x2320;
 
     private static Logger log = LoggerFactory.getLogger(RoleManager.class);
@@ -49,10 +54,10 @@
 
     // the expectation set by the caller for the returned role
     private RoleRecvStatus expectation;
-    private AbstractOpenFlowSwitch sw;
+    private final OpenFlowSwitchDriver sw;
 
 
-    public RoleManager(AbstractOpenFlowSwitch sw) {
+    public RoleManager(OpenFlowSwitchDriver sw) {
         this.requestPending = false;
         this.pendingXid = -1;
         this.pendingRole = null;
@@ -122,33 +127,13 @@
         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)
+    @Override
+    public synchronized boolean sendRoleRequest(RoleState role, RoleRecvStatus exp)
             throws IOException {
         this.expectation = exp;
 
         if (sw.factory().getVersion() == OFVersion.OF_10) {
-            Boolean supportsNxRole = (Boolean)
-                    sw.supportNxRole();
+            Boolean supportsNxRole = sw.supportNxRole();
             if (!supportsNxRole) {
                 log.debug("Switch driver indicates no support for Nicira "
                         + "role request messages. Not sending ...");
@@ -189,23 +174,9 @@
 
     }
 
-    /**
-     * 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)
+
+    @Override
+    public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
             throws SwitchStateException {
         if (!requestPending) {
             RoleState currentRole = (sw != null) ? sw.getRole() : null;
@@ -280,12 +251,13 @@
      * error messages for earlier role requests that we won't be able
      * to handle
      */
-    synchronized RoleRecvStatus deliverError(OFErrorMsg error)
+    @Override
+    public 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());
+                    sw.getStringId());
             return RoleRecvStatus.OTHER_EXPECTATION;
         }
         if (pendingXid != error.getXid()) {
@@ -353,7 +325,8 @@
      * @throws SwitchStateException If the message is a Nicira role reply
      * but the numeric role value is unknown.
      */
-    protected RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg)
+    @Override
+    public RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg)
             throws SwitchStateException {
         int vendor = (int) experimenterMsg.getExperimenter();
         if (vendor != 0x2320) {
@@ -389,72 +362,14 @@
     }
 
     /**
-     * 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
+     * @param rrmsg the role message
      * @return RoleReplyInfo object
-     * @throws SwitchStateException
+     * @throws SwitchStateException if the role information could not be extracted.
      */
-    protected RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg)
+    @Override
+    public RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg)
             throws SwitchStateException {
         OFControllerRole cr = rrmsg.getRole();
         RoleState role = null;
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeAlreadyStarted.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeAlreadyStarted.java
deleted file mode 100644
index 53227aa..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeAlreadyStarted.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.onlab.onos.of.controller.impl.internal;
-
-/**
- * Thrown when IOFSwitch.startDriverHandshake() is called more than once.
- *
- */
-public class SwitchDriverSubHandshakeAlreadyStarted extends
-    SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -5491845708752443501L;
-
-    public SwitchDriverSubHandshakeAlreadyStarted() {
-        super();
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeCompleted.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeCompleted.java
deleted file mode 100644
index ba792e5..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeCompleted.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.onlab.onos.of.controller.impl.internal;
-
-import org.projectfloodlight.openflow.protocol.OFMessage;
-
-
-/**
- * Indicates that a message was passed to a switch driver's subhandshake
- * handling code but the driver has already completed the sub-handshake.
- *
- */
-public class SwitchDriverSubHandshakeCompleted
-        extends SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -8817822245846375995L;
-
-    public SwitchDriverSubHandshakeCompleted(OFMessage m) {
-        super("Sub-Handshake is already complete but received message "
-              + m.getType());
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeException.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeException.java
deleted file mode 100644
index 49fdead..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.onlab.onos.of.controller.impl.internal;
-
-/**
- * Base class for exception thrown by switch driver sub-handshake processing.
- *
- */
-public class SwitchDriverSubHandshakeException extends RuntimeException {
-    private static final long serialVersionUID = -6257836781419604438L;
-
-    protected SwitchDriverSubHandshakeException() {
-        super();
-    }
-
-    protected SwitchDriverSubHandshakeException(String arg0, Throwable arg1) {
-        super(arg0, arg1);
-    }
-
-    protected SwitchDriverSubHandshakeException(String arg0) {
-        super(arg0);
-    }
-
-    protected SwitchDriverSubHandshakeException(Throwable arg0) {
-        super(arg0);
-    }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeNotStarted.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeNotStarted.java
deleted file mode 100644
index 72b17dc..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeNotStarted.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.onlab.onos.of.controller.impl.internal;
-
-/**
- * Thrown when a switch driver's sub-handshake has not been started but an
- * operation requiring the sub-handshake has been attempted.
- *
- */
-public class SwitchDriverSubHandshakeNotStarted extends
-    SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -5491845708752443501L;
-
-    public SwitchDriverSubHandshakeNotStarted() {
-        super();
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeStateException.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeStateException.java
deleted file mode 100644
index 191d1bb..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchDriverSubHandshakeStateException.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.onlab.onos.of.controller.impl.internal;
-
-/**
- * Thrown when a switch driver's sub-handshake state-machine receives an
- * unexpected OFMessage and/or is in an invald state.
- *
- */
-public class SwitchDriverSubHandshakeStateException extends
-    SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -8249926069195147051L;
-
-    public SwitchDriverSubHandshakeStateException(String msg) {
-        super(msg);
-    }
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchStateException.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchStateException.java
deleted file mode 100644
index d82e917..0000000
--- a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/SwitchStateException.java
+++ /dev/null
@@ -1,50 +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;
-
-/**
- * This exception indicates an error or unexpected message during
- * message handling. E.g., if an OFMessage is received that is illegal or
- * unexpected given the current handshake state.
- *
- * We don't allow wrapping other exception in a switch state exception. We
- * only log the SwitchStateExceptions message so the causing exceptions
- * stack trace is generally not available.
- *
- */
-public class SwitchStateException extends Exception {
-
-    private static final long serialVersionUID = 9153954512470002631L;
-
-    public SwitchStateException() {
-        super();
-    }
-
-    public SwitchStateException(String arg0, Throwable arg1) {
-        super(arg0, arg1);
-    }
-
-    public SwitchStateException(String arg0) {
-        super(arg0);
-    }
-
-    public SwitchStateException(Throwable arg0) {
-        super(arg0);
-    }
-
-}
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java
index b475c91..97f94d3 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/DriverManager.java
@@ -3,11 +3,9 @@
 
 
 import org.onlab.onos.of.controller.Dpid;
-import org.onlab.onos.of.controller.RoleState;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
+import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriverFactory;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
-import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -16,7 +14,7 @@
  * A simple implementation of a driver manager that differentiates between
  * connected switches using the OF Description Statistics Reply message.
  */
-public final class DriverManager {
+public final class DriverManager implements OpenFlowSwitchDriverFactory {
 
     private static final Logger log = LoggerFactory.getLogger(DriverManager.class);
 
@@ -32,7 +30,8 @@
      * @return A IOFSwitch instance if the driver found an implementation for
      *         the given description. Otherwise it returns OFSwitchImplBase
      */
-    public static AbstractOpenFlowSwitch getOFSwitchImpl(Dpid dpid,
+    @Override
+    public OpenFlowSwitchDriver getOFSwitchImpl(Dpid dpid,
             OFDescStatsReply desc, OFVersion ofv) {
         String vendor = desc.getMfrDesc();
         String hw = desc.getHwDesc();
@@ -53,42 +52,7 @@
 
         log.warn("DriverManager could not identify switch desc: {}. "
                 + "Assigning OFSwitchImplBase", desc);
-        AbstractOpenFlowSwitch base = new AbstractOpenFlowSwitch(dpid) {
-
-
-            @Override
-            public void sendMsg(OFMessage m) {
-                channel.write(m);
-            }
-
-            @Override
-            public Boolean supportNxRole() {
-                return false;
-            }
-
-            @Override
-            public void startDriverHandshake() {}
-
-            @Override
-            public void setFeaturesReply(OFFeaturesReply featuresReply) {
-                this.features = featuresReply;
-            }
-
-            @Override
-            public void processDriverHandshakeMessage(OFMessage m) {}
-
-            @Override
-            public boolean isDriverHandshakeComplete() {
-                return true;
-            }
-
-            @Override
-            public RoleState getRole() {
-                return role;
-            }
-        };
-        base.setSwitchDescription(desc);
-        return base;
+        return null;
     }
 
     /**
@@ -108,4 +72,10 @@
     public static void setConfigForCpqd(boolean usePipeline13) {
         cpqdUsePipeline13 = usePipeline13;
     }
+
+    public static OpenFlowSwitchDriver getSwitch(Dpid dpid,
+            OFDescStatsReply desc, OFVersion ofv) {
+        return new DriverManager().getOFSwitchImpl(dpid, desc, ofv);
+    }
+
 }
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java
index 6f78e8f..b2881ba 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplCPqD13.java
@@ -10,15 +10,14 @@
 
 import org.onlab.onos.of.controller.Dpid;
 import org.onlab.onos.of.controller.RoleState;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeAlreadyStarted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeCompleted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeCompleted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeNotStarted;
 import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
 import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
 import org.projectfloodlight.openflow.protocol.OFBucket;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFErrorMsg;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
@@ -61,11 +60,11 @@
  */
 public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {
 
-    private Logger log =
+    private final Logger log =
             LoggerFactory.getLogger(OFSwitchImplCPqD13.class);
 
     private static final int VLAN_ID_OFFSET = 16;
-    private AtomicBoolean driverHandshakeComplete;
+    private final AtomicBoolean driverHandshakeComplete;
     private OFFactory factory;
     private static final int OFPCML_NO_BUFFER = 0xffff;
     // Configuration of asynch messages to controller. We need different
@@ -96,7 +95,7 @@
     private static final short MIN_PRIORITY = 0x0;
     private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);
 
-    private Map<Integer, OFGroup> l2groups;
+    private final Map<Integer, OFGroup> l2groups;
 
     private final boolean usePipeline13;
 
@@ -131,7 +130,7 @@
             // Send packet-in to controller if a packet misses the first table
             populateTableMissEntry(0, true, false, false, 0);
         } //else {
-            // configureSwitch();
+        // configureSwitch();
         //}
         sendBarrier(true);
     }
@@ -146,14 +145,7 @@
 
     @Override
     public void processDriverHandshakeMessage(OFMessage m) {
-        if (!startDriverHandshakeCalled) {
-            throw new SwitchDriverSubHandshakeNotStarted();
-        }
-        if (driverHandshakeComplete.get()) {
-            throw new SwitchDriverSubHandshakeCompleted(m);
-        }
-
-        if (!startDriverHandshakeCalled) {
+        if (!startDriverHandshakeCalled || !startDriverHandshakeCalled) {
             throw new SwitchDriverSubHandshakeNotStarted();
         }
         if (driverHandshakeComplete.get()) {
@@ -168,30 +160,23 @@
             break;
 
         case ERROR:
-            log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
+            log.error("Switch {} Error {}", getStringId(), m);
             break;
 
-        case FEATURES_REPLY:
-            break;
-        case FLOW_REMOVED:
-            break;
         case GET_ASYNC_REPLY:
             OFAsyncGetReply asrep = (OFAsyncGetReply) m;
             decodeAsyncGetReply(asrep);
             break;
-
-        case PACKET_IN:
-            break;
-        case PORT_STATUS:
-            break;
-        case QUEUE_GET_CONFIG_REPLY:
-            break;
-        case ROLE_REPLY:
-            break;
-
         case STATS_REPLY:
             processStatsReply((OFStatsReply) m);
             break;
+        case PACKET_IN:
+        case PORT_STATUS:
+        case QUEUE_GET_CONFIG_REPLY:
+        case ROLE_REPLY:
+        case FEATURES_REPLY:
+        case FLOW_REMOVED:
+            break;
 
         default:
             log.debug("Received message {} during switch-driver subhandshake "
@@ -254,7 +239,7 @@
                 .build();
         msglist.add(getAC);
 
-        write(msglist);
+        sendMsg(msglist);
     }
 
     private void decodeAsyncGetReply(OFAsyncGetReply rep) {
@@ -327,7 +312,7 @@
             }
         }
         log.debug("Creating {} L2 groups in sw {}", msglist.size(), getStringId());
-        write(msglist);
+        sendMsg(msglist);
     }
 
     private int getVlanConfig(int portnum) {
@@ -405,9 +390,9 @@
 
             List<OFAction> actions = new ArrayList<OFAction>();
             actions.add(decTtl); // decrement the IP TTL/do-checksum/check TTL
-                                 // and MTU
+            // and MTU
             actions.add(setVlan); // set the vlan-id of the exit-port (and
-                                  // l2group)
+            // l2group)
             actions.add(setSA); // set this routers mac address
             // make L3Unicast group setDA for known (configured) ports
             // that connect to other routers
@@ -428,7 +413,7 @@
                     .build();
             msglist.add(gmAdd);
         }
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Creating {} L3 groups in sw {}", msglist.size(), getStringId());
     }
 
@@ -449,8 +434,8 @@
             // setDA will only be non-null for ports connected to routers
             if (setDA != null) {
                 OFGroup gl3 = OFGroup.of(0xa0000000 | portnum); // different id
-                                                                // for mpls
-                                                                // group
+                // for mpls
+                // group
                 OFAction group = factory.actions().buildGroup()
                         .setGroup(gl2).build();
                 OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
@@ -462,9 +447,9 @@
                 OFAction decMplsTtl = factory.actions().decMplsTtl();
                 List<OFAction> actions = new ArrayList<OFAction>();
                 actions.add(decMplsTtl); // decrement the MPLS
-                                         // TTL/do-checksum/check TTL and MTU
+                // TTL/do-checksum/check TTL and MTU
                 actions.add(setVlan); // set the vlan-id of the exit-port (and
-                                      // l2group)
+                // l2group)
                 actions.add(setSA); // set this routers mac address
                 actions.add(setDA);
                 actions.add(group);
@@ -480,7 +465,7 @@
                 msglist.add(gmAdd);
             }
         }
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Creating {} MPLS groups in sw {}", msglist.size(), getStringId());
     }
 
@@ -586,7 +571,7 @@
                         .setMatch(match)
                         .setInstructions(instructions)
                         .setPriority(1000) // does not matter - all rules
-                                           // exclusive
+                        // exclusive
                         .setBufferId(OFBufferId.NO_BUFFER)
                         .setIdleTimeout(0)
                         .setHardTimeout(0)
@@ -597,7 +582,7 @@
         }
         // table-vlan has no table-miss entry, and so packets that miss are
         // essentially dropped
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Adding {} vlan-rules in sw {}", msglist.size(), getStringId());
     }
 
@@ -615,7 +600,7 @@
                 .setMatch(matchIp)
                 .setInstructions(instructionsIp)
                 .setPriority(1000) // strict priority required lower than
-                                   // multicastMac
+                // multicastMac
                 .setBufferId(OFBufferId.NO_BUFFER)
                 .setIdleTimeout(0)
                 .setHardTimeout(0)
@@ -635,7 +620,7 @@
                 .setMatch(matchMpls)
                 .setInstructions(instructionsMpls)
                 .setPriority(1001) // strict priority required lower than
-                                   // multicastMac
+                // multicastMac
                 .setBufferId(OFBufferId.NO_BUFFER)
                 .setIdleTimeout(0)
                 .setHardTimeout(0)
@@ -649,7 +634,7 @@
         List<OFMessage> msglist = new ArrayList<OFMessage>(2);
         msglist.add(ipEntry);
         msglist.add(mplsEntry);
-        write(msglist);
+        sendMsg(msglist);
     }
 
     private List<String> getMyIps() { // send to controller
@@ -712,13 +697,13 @@
         List<RouteEntry> routerNextHopIps = new ArrayList<RouteEntry>();
         if (getId() == 0x1) {
             routerNextHopIps
-                    .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
+            .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
             routerNextHopIps
-                    .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
+            .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
             routerNextHopIps.add(new RouteEntry("7.7.7.0", "255.255.255.0", 6, 103));
         }
         //if (getId() == 0x2) {
-            /* These are required for normal IP routing without labels.
+        /* These are required for normal IP routing without labels.
             routerNextHopIps.add(new RouteEntry("192.168.0.1","255.255.255.255",1));
             routerNextHopIps.add(new RouteEntry("192.168.0.3","255.255.255.255",2));
             routerNextHopIps.add(new RouteEntry("10.0.1.0","255.255.255.0",1));
@@ -728,9 +713,9 @@
         //}
         if (getId() == 0x3) {
             routerNextHopIps
-                    .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
+            .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
             routerNextHopIps
-                    .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
+            .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
             routerNextHopIps.add(new RouteEntry("10.0.1.0", "255.255.255.0", 2, 101));
             routerNextHopIps.add(new RouteEntry("10.0.2.0", "255.255.255.0", 2, 101));
             routerNextHopIps.add(new RouteEntry("10.0.3.0", "255.255.255.0", 2, 101));
@@ -794,7 +779,7 @@
                     .setMatch(match)
                     .setInstructions(instructions)
                     .setPriority(MAX_PRIORITY) // highest priority for exact
-                                               // match
+                    // match
                     .setBufferId(OFBufferId.NO_BUFFER)
                     .setIdleTimeout(0)
                     .setHardTimeout(0)
@@ -802,7 +787,7 @@
                     .build();
             msglist.add(myIpEntry);
         }
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Adding {} my-ip-rules in sw {}", msglist.size(), getStringId());
     }
 
@@ -844,7 +829,7 @@
                     .build();
             msglist.add(myIpEntry);
         }
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Adding {} subnet-ip-rules in sw {}", msglist.size(), getStringId());
         msglist.clear();
     }
@@ -861,14 +846,14 @@
                     .ipv4DstMasked(
                             IPv4Address.of(routerNextHopIps.get(i).prefix),
                             IPv4Address.of(routerNextHopIps.get(i).mask)
-                    );
+                            );
             OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
             OFMatchV3 match = factory.buildMatchV3()
                     .setOxmList(oxmListSlash32).build();
             OFAction outg = factory.actions().buildGroup()
                     .setGroup(OFGroup.of(0xa0000000 | // mpls group id
                             routerNextHopIps.get(i).nextHopPort))
-                    .build();
+                            .build();
             // lots of actions before forwarding to mpls group, and
             // unfortunately
             // they need to be apply-actions
@@ -887,7 +872,7 @@
             writeActions.add(copyTtlOut); // matched in pseudo-table
             //writeActions.add(setlabelid); // bad support in cpqd
             //writeActions.add(setBos); no support in loxigen
-            */
+             */
 
             List<OFAction> applyActions = new ArrayList<OFAction>();
             applyActions.add(pushlabel);
@@ -896,7 +881,7 @@
                     .setActions(applyActions).build();
             List<OFAction> writeActions = new ArrayList<OFAction>();
             writeActions.add(outg); // group will decr mpls-ttl, set mac-sa/da,
-                                    // vlan
+            // vlan
             OFInstruction writeInstr = factory.instructions().buildWriteActions()
                     .setActions(writeActions).build();
 
@@ -950,7 +935,7 @@
             OFAction outg2 = factory.actions().buildGroup()
                     .setGroup(OFGroup.of(routerNextHopIps.get(i).nextHopPort |
                             (192 << VLAN_ID_OFFSET)))
-                    .build();
+                            .build();
             writeActions2.add(outg2);
             OFInstruction writeInstr2 = factory.instructions().buildWriteActions()
                     .setActions(writeActions2).build();
@@ -989,7 +974,7 @@
             msglist.add(myMetaEntry);
 
         }
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Adding {} next-hop-router-rules in sw {}", msglist.size(),
                 getStringId());
 
@@ -1022,7 +1007,7 @@
                     .setField(dmac).build();
             outg = factory.actions().buildGroup()
                     .setGroup(OFGroup.of(0x20000000 | hostNextHopIps.get(i).nextHopPort)) // l3group
-                                                                                          // id
+                    // id
                     .build();
             List<OFAction> writeActions = new ArrayList<OFAction>();
             writeActions.add(setDmac);
@@ -1039,7 +1024,7 @@
                     .setMatch(match)
                     .setInstructions(instructions)
                     .setPriority(MAX_PRIORITY) // highest priority for exact
-                                               // match
+                    // match
                     .setBufferId(OFBufferId.NO_BUFFER)
                     .setIdleTimeout(0)
                     .setHardTimeout(0)
@@ -1047,7 +1032,7 @@
                     .build();
             msglist.add(myIpEntry);
         }
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Adding {} next-hop-host-rules in sw {}", msglist.size(), getStringId());
     }
 
@@ -1121,7 +1106,7 @@
                     .build();
             msglist.add(myMplsEntry);
         }
-        write(msglist);
+        sendMsg(msglist);
         log.debug("Adding {} mpls-forwarding-rules in sw {}", msglist.size(),
                 getStringId());
 
@@ -1190,7 +1175,7 @@
             // executed - if there is an action to output/group in the action
             // set
             // the packet will be sent there, otherwise it will be dropped.
-            instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
+            instructions = Collections.EMPTY_LIST;
         }
 
         OFMessage tableMissEntry = factory.buildFlowAdd()
@@ -1219,20 +1204,19 @@
     }
 
     @Override
-    public void sendMsg(OFMessage m) {
-        channel.write(m);
+    public Boolean supportNxRole() {
+        return false;
+    }
+
+    @Override
+    public void write(OFMessage msg) {
+        this.channel.write(msg);
+
     }
 
     @Override
     public void write(List<OFMessage> msgs) {
-        for (OFMessage m : msgs) {
-            channel.write(m);
-        }
-    }
-
-    @Override
-    public Boolean supportNxRole() {
-        return false;
+        this.channel.write(msgs);
     }
 
 }
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java
index 45228dc..bc42636 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS10.java
@@ -1,7 +1,9 @@
 package org.onlab.onos.of.drivers;
 
+import java.util.List;
+
 import org.onlab.onos.of.controller.Dpid;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 
@@ -29,11 +31,6 @@
     }
 
     @Override
-    public void sendMsg(OFMessage m) {
-        channel.write(m);
-    }
-
-    @Override
     public Boolean supportNxRole() {
         return true;
     }
@@ -48,4 +45,15 @@
 
     @Override
     public void processDriverHandshakeMessage(OFMessage m) {}
+
+    @Override
+    public void write(OFMessage msg) {
+        channel.write(msg);
+
+    }
+
+    @Override
+    public void write(List<OFMessage> msgs) {
+        channel.write(msgs);
+    }
 }
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java
index 1ab1f047..40750f7 100644
--- a/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java
+++ b/of/ctl/src/main/java/org/onlab/onos/of/drivers/OFSwitchImplOVS13.java
@@ -1,15 +1,15 @@
 package org.onlab.onos.of.drivers;
 
+import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.onlab.onos.of.controller.Dpid;
-import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeAlreadyStarted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeCompleted;
-import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted;
+import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeCompleted;
+import org.onlab.onos.of.controller.driver.SwitchDriverSubHandshakeNotStarted;
 import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFErrorMsg;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.slf4j.Logger;
@@ -25,7 +25,7 @@
     private static Logger log =
             LoggerFactory.getLogger(OFSwitchImplOVS13.class);
 
-    private AtomicBoolean driverHandshakeComplete;
+    private final AtomicBoolean driverHandshakeComplete;
     private OFFactory factory;
     private long barrierXidToWaitFor = -1;
 
@@ -78,7 +78,7 @@
             break;
 
         case ERROR:
-            log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
+            log.error("Switch {} Error {}", getStringId(), m);
             break;
 
         case FEATURES_REPLY:
@@ -129,12 +129,18 @@
     }
 
     @Override
-    public void sendMsg(OFMessage m) {
-        channel.write(m);
+    public Boolean supportNxRole() {
+        return false;
     }
 
     @Override
-    public Boolean supportNxRole() {
-        return false;
+    public void write(OFMessage msg) {
+        channel.write(msg);
+
+    }
+
+    @Override
+    public void write(List<OFMessage> msgs) {
+        channel.write(msgs);
     }
 }