Moving /of to /openflow
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/DefaultOpenFlowPacketContext.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/DefaultOpenFlowPacketContext.java
new file mode 100644
index 0000000..45f615a
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/DefaultOpenFlowPacketContext.java
@@ -0,0 +1,120 @@
+package org.onlab.onos.of.controller;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.onlab.packet.Ethernet;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.slf4j.Logger;
+
+public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
+
+    private final Logger log = getLogger(getClass());
+
+    private final AtomicBoolean free = new AtomicBoolean(true);
+    private final AtomicBoolean isBuilt = new AtomicBoolean(false);
+    private final OpenFlowSwitch sw;
+    private final OFPacketIn pktin;
+    private OFPacketOut pktout = null;
+
+    private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
+        this.sw = s;
+        this.pktin = pkt;
+    }
+
+    @Override
+    public void send() {
+        if (block() && isBuilt.get()) {
+            sw.sendMsg(pktout);
+        }
+    }
+
+    @Override
+    public void build(OFPort outPort) {
+        if (isBuilt.getAndSet(true)) {
+            return;
+        }
+        OFPacketOut.Builder builder = sw.factory().buildPacketOut();
+        OFAction act = buildOutput(outPort.getPortNumber());
+        pktout = builder.setXid(pktin.getXid())
+                .setInPort(pktin.getInPort())
+                .setBufferId(pktin.getBufferId())
+                .setActions(Collections.singletonList(act))
+                .build();
+    }
+
+    @Override
+    public void build(Ethernet ethFrame, OFPort outPort) {
+        if (isBuilt.getAndSet(true)) {
+            return;
+        }
+        OFPacketOut.Builder builder = sw.factory().buildPacketOut();
+        OFAction act = buildOutput(outPort.getPortNumber());
+        pktout = builder.setXid(pktin.getXid())
+                .setBufferId(OFBufferId.NO_BUFFER)
+                .setInPort(pktin.getInPort())
+                .setActions(Collections.singletonList(act))
+                .setData(ethFrame.serialize())
+                .build();
+    }
+
+    @Override
+    public Ethernet parsed() {
+        Ethernet eth = new Ethernet();
+        eth.deserialize(pktin.getData(), 0, pktin.getTotalLen());
+        return eth;
+    }
+
+    @Override
+    public Dpid dpid() {
+        return new Dpid(sw.getId());
+    }
+
+    public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
+            OFPacketIn pkt) {
+        return new DefaultOpenFlowPacketContext(s, pkt);
+    }
+
+    @Override
+    public Integer inPort() {
+        try {
+            return pktin.getInPort().getPortNumber();
+        } catch (UnsupportedOperationException e) {
+            return pktin.getMatch().get(MatchField.IN_PORT).getPortNumber();
+        }
+    }
+
+    @Override
+    public byte[] unparsed() {
+
+        return pktin.getData().clone();
+
+    }
+
+    private OFActionOutput buildOutput(Integer port) {
+        OFActionOutput act = sw.factory().actions()
+                .buildOutput()
+                .setPort(OFPort.of(port))
+                .build();
+        return act;
+    }
+
+    @Override
+    public boolean block() {
+        return free.getAndSet(false);
+    }
+
+    @Override
+    public boolean isHandled() {
+        return !free.get();
+    }
+
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/Dpid.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/Dpid.java
new file mode 100644
index 0000000..ca3d8e6
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/Dpid.java
@@ -0,0 +1,119 @@
+package org.onlab.onos.of.controller;
+
+import org.projectfloodlight.openflow.util.HexString;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onlab.util.Tools.fromHex;
+import static org.onlab.util.Tools.toHex;
+
+/**
+ * The class representing a network switch DPID.
+ * This class is immutable.
+ */
+public final class Dpid {
+
+    private static final String SCHEME = "of";
+    private static final long UNKNOWN = 0;
+    private final long value;
+
+    /**
+     * Default constructor.
+     */
+    public Dpid() {
+        this.value = Dpid.UNKNOWN;
+    }
+
+    /**
+     * Constructor from a long value.
+     *
+     * @param value the value to use.
+     */
+    public Dpid(long value) {
+        this.value = value;
+    }
+
+    /**
+     * Constructor from a string.
+     *
+     * @param value the value to use.
+     */
+    public Dpid(String value) {
+        this.value = HexString.toLong(value);
+    }
+
+    /**
+     * Get the value of the DPID.
+     *
+     * @return the value of the DPID.
+     */
+    public long value() {
+        return value;
+    }
+
+    /**
+     * Convert the DPID value to a ':' separated hexadecimal string.
+     *
+     * @return the DPID value as a ':' separated hexadecimal string.
+     */
+    @Override
+    public String toString() {
+        return HexString.toHexString(this.value);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof Dpid)) {
+            return false;
+        }
+
+        Dpid otherDpid = (Dpid) other;
+
+        return value == otherDpid.value;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 17;
+        hash += 31 * hash + (int) (value ^ value >>> 32);
+        return hash;
+    }
+
+    /**
+     * Returns DPID created from the given device URI.
+     *
+     * @param uri device URI
+     * @return dpid
+     */
+    public static Dpid dpid(URI uri) {
+        checkArgument(uri.getScheme().equals(SCHEME), "Unsupported URI scheme");
+        return new Dpid(fromHex(uri.getSchemeSpecificPart()));
+    }
+
+    /**
+     * Produces device URI from the given DPID.
+     *
+     * @param dpid device dpid
+     * @return device URI
+     */
+    public static URI uri(Dpid dpid) {
+        return uri(dpid.value);
+    }
+
+    /**
+     * Produces device URI from the given DPID long.
+     *
+     * @param value device dpid as long
+     * @return device URI
+     */
+    public static URI uri(long value) {
+        try {
+            return new URI(SCHEME, toHex(value), null);
+        } catch (URISyntaxException e) {
+            return null;
+        }
+    }
+
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowController.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowController.java
new file mode 100644
index 0000000..ab80eee
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowController.java
@@ -0,0 +1,101 @@
+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 dpid the dpid the message arrived on
+     * @param msg the message to process.
+     */
+    public void processPacket(Dpid dpid, 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/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowPacketContext.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowPacketContext.java
new file mode 100644
index 0000000..0e90f95
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowPacketContext.java
@@ -0,0 +1,69 @@
+package org.onlab.onos.of.controller;
+
+import org.onlab.packet.Ethernet;
+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 OpenFlowPacketContext {
+
+    //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 boolean block();
+
+    /**
+     * Checks whether the packet has been handled.
+     * @return true if handled, false otherwise.
+     */
+    public boolean isHandled();
+
+    /**
+     * 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(Ethernet ethFrame, OFPort outPort);
+
+    /**
+     * Provided a handle onto the parsed payload.
+     * @return the parsed form of the payload.
+     */
+    public Ethernet parsed();
+
+    /**
+     * Provide an unparsed copy of the data.
+     * @return the unparsed form of the payload.
+     */
+    public byte[] unparsed();
+
+    /**
+     * Provide the dpid of the switch where the packet in arrived.
+     * @return the dpid of the switch.
+     */
+    public Dpid dpid();
+
+    /**
+     * Provide the port on which the packet arrived.
+     * @return the port
+     */
+    public Integer inPort();
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java
new file mode 100644
index 0000000..f16bb88
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitch.java
@@ -0,0 +1,108 @@
+package org.onlab.onos.of.controller;
+
+import java.util.List;
+
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+
+/**
+ * Represents to provider facing side of a switch.
+ */
+public interface OpenFlowSwitch {
+
+    /**
+     * Writes the message to the driver.
+     *
+     * @param msg the message to write
+     */
+    public void sendMsg(OFMessage msg);
+
+    /**
+     * Writes to the OFMessage list to the driver.
+     *
+     * @param msgs the messages to be written
+     */
+    public void sendMsg(List<OFMessage> msgs);
+
+    /**
+     * Handle a message from the switch.
+     * @param fromSwitch the message to handle
+     */
+    public void handleMessage(OFMessage fromSwitch);
+
+    /**
+     * Sets the role for this switch.
+     * @param role the role to set.
+     */
+    public void setRole(RoleState role);
+
+    /**
+     * Fetch the role for this switch.
+     * @return the role.
+     */
+    public RoleState getRole();
+
+    /**
+     * Fetches the ports of this switch.
+     * @return unmodifiable list of the ports.
+     */
+    public List<OFPortDesc> getPorts();
+
+    /**
+     * Provides the factory for this OF version.
+     * @return OF version specific factory.
+     */
+    public OFFactory factory();
+
+    /**
+     * Gets a string version of the ID for this switch.
+     *
+     * @return string version of the ID
+     */
+    public String getStringId();
+
+    /**
+     * Gets the datapathId of the switch.
+     *
+     * @return the switch dpid in long format
+     */
+    public long getId();
+
+    /**
+     * fetch the manufacturer description.
+     * @return the description
+     */
+    public String manfacturerDescription();
+
+    /**
+     * fetch the datapath description.
+     * @return the description
+     */
+    public String datapathDescription();
+
+    /**
+     * fetch the hardware description.
+     * @return the description
+     */
+    public String hardwareDescription();
+
+    /**
+     * fetch the software description.
+     * @return the description
+     */
+    public String softwareDescription();
+
+    /**
+     * fetch the serial number.
+     * @return the serial
+     */
+    public String serialNumber();
+
+    /**
+     * Disconnects the switch by closing the TCP connection. Results in a call
+     * to the channel handler's channelDisconnected method for cleanup
+     */
+    public void disconnectSwitch();
+
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchListener.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchListener.java
new file mode 100644
index 0000000..ae5e3a8
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/OpenFlowSwitchListener.java
@@ -0,0 +1,28 @@
+package org.onlab.onos.of.controller;
+
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
+
+/**
+ * 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);
+
+    /**
+     * Notify that a port has changed.
+     * @param dpid the switch on which the change happened.
+     * @param status the new state of the port.
+     */
+    public void portChanged(Dpid dpid, OFPortStatus status);
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/PacketListener.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/PacketListener.java
new file mode 100644
index 0000000..6bd39b8
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/PacketListener.java
@@ -0,0 +1,14 @@
+package org.onlab.onos.of.controller;
+
+/**
+ * Notifies providers about Packet in events.
+ */
+public interface PacketListener {
+
+    /**
+     * Handles the packet.
+     *
+     * @param pktCtx the packet context
+     */
+    public void handlePacket(OpenFlowPacketContext pktCtx);
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/RoleState.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/RoleState.java
new file mode 100644
index 0000000..db8efd1
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/RoleState.java
@@ -0,0 +1,25 @@
+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/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/AbstractOpenFlowSwitch.java
new file mode 100644
index 0000000..d7e0186
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/AbstractOpenFlowSwitch.java
@@ -0,0 +1,346 @@
+/**
+ *    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.driver;
+
+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.RoleState;
+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;
+
+/**
+ * An abstract representation of an OpenFlow switch. Can be extended by others
+ * to serve as a base for their vendor specific representation of a switch.
+ */
+public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
+
+    private static Logger log =
+            LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
+
+    protected Channel channel;
+
+    private boolean connected;
+    protected boolean startDriverHandshakeCalled = false;
+    private final Dpid dpid;
+    private OpenFlowAgent agent;
+    private final AtomicInteger xidCounter = new AtomicInteger(0);
+
+    private OFVersion ofVersion;
+
+    protected OFPortDescStatsReply ports;
+
+    protected boolean tableFull;
+
+    private RoleHandler roleMan;
+
+    protected RoleState role;
+
+    protected OFFeaturesReply features;
+    protected OFDescStatsReply desc;
+
+    /**
+     * Given a dpid build this switch.
+     * @param dp the dpid
+     */
+    protected AbstractOpenFlowSwitch(Dpid dp) {
+        this.dpid = dp;
+    }
+
+    public AbstractOpenFlowSwitch(Dpid dpid, OFDescStatsReply desc) {
+        this.dpid = dpid;
+        this.desc = desc;
+    }
+
+    //************************
+    // Channel related
+    //************************
+
+    @Override
+    public final void disconnectSwitch() {
+        this.channel.close();
+    }
+
+    @Override
+    public final void sendMsg(OFMessage m) {
+        this.write(m);
+    }
+
+    @Override
+    public final void sendMsg(List<OFMessage> msgs) {
+        this.write(msgs);
+    }
+
+    @Override
+    public abstract void write(OFMessage msg);
+
+    @Override
+    public abstract void write(List<OFMessage> msgs);
+
+    @Override
+    public final boolean isConnected() {
+        return this.connected;
+    }
+
+    @Override
+    public final void setConnected(boolean connected) {
+        this.connected = connected;
+    };
+
+    @Override
+    public final void setChannel(Channel channel) {
+        this.channel = channel;
+    };
+
+    //************************
+    // Switch features related
+    //************************
+
+    @Override
+    public final long getId() {
+        return this.dpid.value();
+    };
+
+    @Override
+    public final String getStringId() {
+        return this.dpid.toString();
+    }
+
+    @Override
+    public final void setOFVersion(OFVersion ofV) {
+        this.ofVersion = ofV;
+    }
+
+    @Override
+    public void setTableFull(boolean full) {
+        this.tableFull = full;
+    }
+
+    @Override
+    public void setFeaturesReply(OFFeaturesReply featuresReply) {
+        this.features = featuresReply;
+    }
+
+    @Override
+    public abstract Boolean supportNxRole();
+
+    //************************
+    //  Message handling
+    //************************
+    /**
+     * Handle the message coming from the dataplane.
+     *
+     * @param m the actual message
+     */
+    @Override
+    public final void handleMessage(OFMessage m) {
+        this.agent.processMessage(dpid, m);
+    }
+
+    @Override
+    public RoleState getRole() {
+        return role;
+    };
+
+    @Override
+    public final boolean connectSwitch() {
+        return this.agent.addConnectedSwitch(dpid, this);
+    }
+
+    @Override
+    public final boolean activateMasterSwitch() {
+        return this.agent.addActivatedMasterSwitch(dpid, this);
+    }
+
+    @Override
+    public final boolean activateEqualSwitch() {
+        return this.agent.addActivatedEqualSwitch(dpid, this);
+    }
+
+    @Override
+    public final void transitionToEqualSwitch() {
+        this.agent.transitionToEqualSwitch(dpid);
+    }
+
+    @Override
+    public final void transitionToMasterSwitch() {
+        this.agent.transitionToMasterSwitch(dpid);
+    }
+
+    @Override
+    public final void removeConnectedSwitch() {
+        this.agent.removeConnectedSwitch(dpid);
+    }
+
+    @Override
+    public OFFactory factory() {
+        return OFFactories.getFactory(ofVersion);
+    }
+
+    @Override
+    public void setPortDescReply(OFPortDescStatsReply portDescReply) {
+        this.ports = portDescReply;
+    }
+
+    @Override
+    public abstract void startDriverHandshake();
+
+    @Override
+    public abstract boolean isDriverHandshakeComplete();
+
+    @Override
+    public abstract void processDriverHandshakeMessage(OFMessage m);
+
+    @Override
+    public void setRole(RoleState role) {
+        try {
+            log.info("Sending role {} to switch {}", role, getStringId());
+            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
+
+    @Override
+    public 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();
+            }
+        }
+    }
+
+    @Override
+    public 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();
+            }
+        }
+    }
+
+    @Override
+    public boolean handleRoleError(OFErrorMsg error) {
+        try {
+            return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
+        } catch (SwitchStateException e) {
+            this.disconnectSwitch();
+        }
+        return true;
+    }
+
+    @Override
+    public void reassertRole() {
+        if (this.getRole() == RoleState.MASTER) {
+            this.setRole(RoleState.MASTER);
+        }
+    }
+
+    @Override
+    public final void setAgent(OpenFlowAgent ag) {
+        if (this.agent == null) {
+            this.agent = ag;
+        }
+    }
+
+    @Override
+    public final void setRoleHandler(RoleHandler roleHandler) {
+        if (this.roleMan == null) {
+            this.roleMan = roleHandler;
+        }
+    }
+
+    @Override
+    public void setSwitchDescription(OFDescStatsReply d) {
+        this.desc = d;
+    }
+
+    @Override
+    public int getNextTransactionId() {
+        return this.xidCounter.getAndIncrement();
+    }
+
+    @Override
+    public List<OFPortDesc> getPorts() {
+        return Collections.unmodifiableList(ports.getEntries());
+    }
+
+    @Override
+    public String manfacturerDescription() {
+        return this.desc.getMfrDesc();
+    }
+
+
+    @Override
+    public String datapathDescription() {
+        return this.desc.getDpDesc();
+    }
+
+
+    @Override
+    public String hardwareDescription() {
+        return this.desc.getHwDesc();
+    }
+
+    @Override
+    public String softwareDescription() {
+        return this.desc.getSwDesc();
+    }
+
+    @Override
+    public String serialNumber() {
+        return this.desc.getSerialNum();
+    }
+
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowAgent.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowAgent.java
new file mode 100644
index 0000000..0d37666
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowAgent.java
@@ -0,0 +1,77 @@
+package org.onlab.onos.of.controller.driver;
+
+import org.onlab.onos.of.controller.Dpid;
+import org.onlab.onos.of.controller.OpenFlowSwitch;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+/**
+ * Responsible for keeping track of the current set of switches
+ * connected to the system. As well as whether they are in Master
+ * role or not.
+ *
+ */
+public interface OpenFlowAgent {
+
+    /**
+     * Add a switch that has just connected to the system.
+     * @param dpid the dpid to add
+     * @param sw the actual switch object.
+     * @return true if added, false otherwise.
+     */
+    public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw);
+
+    /**
+     * Checks if the activation for this switch is valid.
+     * @param dpid the dpid to check
+     * @return true if valid, false otherwise
+     */
+    public boolean validActivation(Dpid dpid);
+
+    /**
+     * Called when a switch is activated, with this controller's role as MASTER.
+     * @param dpid the dpid to add.
+     * @param sw the actual switch
+     * @return true if added, false otherwise.
+     */
+    public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw);
+
+    /**
+     * Called when a switch is activated, with this controller's role as EQUAL.
+     * @param dpid the dpid to add.
+     * @param sw the actual switch
+     * @return true if added, false otherwise.
+     */
+    public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw);
+
+    /**
+     * 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'.
+     * @param dpid the dpid to transistion.
+     */
+    public void transitionToMasterSwitch(Dpid dpid);
+
+    /**
+     * 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'.
+     * @param dpid the dpid to transistion.
+     */
+    public void transitionToEqualSwitch(Dpid dpid);
+
+    /**
+     * 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.
+     * @param dpid the dpid to remove.
+     */
+    public void removeConnectedSwitch(Dpid dpid);
+
+    /**
+     * Process a message coming from a switch.
+     *
+     * @param dpid the dpid the message came on.
+     * @param m the message to process
+     */
+    public void processMessage(Dpid dpid, OFMessage m);
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriver.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriver.java
new file mode 100644
index 0000000..be99973
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriver.java
@@ -0,0 +1,197 @@
+package org.onlab.onos.of.controller.driver;
+
+import java.util.List;
+
+import org.jboss.netty.channel.Channel;
+import org.onlab.onos.of.controller.OpenFlowSwitch;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+/**
+ * Represents the driver side of an OpenFlow switch.
+ * This interface should never be exposed to consumers.
+ *
+ */
+public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
+
+    /**
+     * Sets the OpenFlow agent to be used. This method
+     * can only be called once.
+     * @param agent the agent to set.
+     */
+    public void setAgent(OpenFlowAgent agent);
+
+    /**
+     * Sets the Role handler object.
+     * This method can only be called once.
+     * @param roleHandler the roleHandler class
+     */
+    public void setRoleHandler(RoleHandler roleHandler);
+
+    /**
+     * Reasserts this controllers role to the switch.
+     * Useful in cases where the switch no longer agrees
+     * that this controller has the role it claims.
+     */
+    public void reassertRole();
+
+    /**
+     * Handle the situation where the role request triggers an error.
+     * @param error the error to handle.
+     * @return true if handled, false if not.
+     */
+    public boolean handleRoleError(OFErrorMsg error);
+
+    /**
+     * If this driver know of Nicira style role messages, these should
+     * be handled here.
+     * @param m the role message to handle.
+     * @throws SwitchStateException if the message received was
+     *  not a nicira role or was malformed.
+     */
+    public void handleNiciraRole(OFMessage m) throws SwitchStateException;
+
+    /**
+     * Handle OF 1.x (where x > 0) role messages.
+     * @param m the role message to handle
+     * @throws SwitchStateException if the message received was
+     *  not a nicira role or was malformed.
+     */
+    public void handleRole(OFMessage m) throws SwitchStateException;
+
+    /**
+     * Starts the driver specific handshake process.
+     */
+    public void startDriverHandshake();
+
+    /**
+     * Checks whether the driver specific handshake is complete.
+     * @return true is finished, false if not.
+     */
+    public boolean isDriverHandshakeComplete();
+
+    /**
+     * Process a message during the driver specific handshake.
+     * @param m the message to process.
+     */
+    public void processDriverHandshakeMessage(OFMessage m);
+
+    /**
+     * Announce to the OpenFlow agent that this switch has connected.
+     * @return true if successful, false if duplicate switch.
+     */
+    public boolean connectSwitch();
+
+    /**
+     * Activate this MASTER switch-controller relationship in the OF agent.
+     * @return true is successful, false is switch has not
+     * connected or is unknown to the system.
+     */
+    public boolean activateMasterSwitch();
+
+    /**
+     * Activate this EQUAL switch-controller relationship in the OF agent.
+     * @return true is successful, false is switch has not
+     * connected or is unknown to the system.
+     */
+    public boolean activateEqualSwitch();
+
+    /**
+     * Transition this switch-controller relationship to an EQUAL state.
+     */
+    public void transitionToEqualSwitch();
+
+    /**
+     * Transition this switch-controller relationship to an Master state.
+     */
+    public void transitionToMasterSwitch();
+
+    /**
+     * Remove this switch from the openflow agent.
+     */
+    public void removeConnectedSwitch();
+
+    /**
+     * Sets the ports on this switch.
+     * @param portDescReply the port set and descriptions
+     */
+    public void setPortDescReply(OFPortDescStatsReply portDescReply);
+
+    /**
+     * Sets the features reply for this switch.
+     * @param featuresReply the features to set.
+     */
+    public void setFeaturesReply(OFFeaturesReply featuresReply);
+
+    /**
+     * Sets the switch description.
+     * @param desc the descriptions
+     */
+    public void setSwitchDescription(OFDescStatsReply desc);
+
+    /**
+     * Gets the next transaction id to use.
+     * @return the xid
+     */
+    public int getNextTransactionId();
+
+
+    /**
+     * Does this switch support Nicira Role messages.
+     * @return true if supports, false otherwise.
+     */
+    public Boolean supportNxRole();
+
+    /**
+     * Sets the OF version for this switch.
+     * @param ofV the version to set.
+     */
+    public void setOFVersion(OFVersion ofV);
+
+    /**
+     * Sets this switch has having a full flowtable.
+     * @param full true if full, false otherswise.
+     */
+    public void setTableFull(boolean full);
+
+    /**
+     * Sets the associated Netty channel for this switch.
+     * @param channel the Netty channel
+     */
+    public void setChannel(Channel channel);
+
+    /**
+     * Sets whether the switch is connected.
+     *
+     * @param connected whether the switch is connected
+     */
+    public void setConnected(boolean connected);
+
+    /**
+     * Checks if the switch is still connected.
+     *
+     * @return whether the switch is still connected
+     */
+    public boolean isConnected();
+
+    /**
+     * Writes the message to the output stream
+     * in a driver specific manner.
+     *
+     * @param msg the message to write
+     */
+    public void write(OFMessage msg);
+
+    /**
+     * Writes to the OFMessage list to the output stream
+     * in a driver specific manner.
+     *
+     * @param msgs the messages to be written
+     */
+    public void write(List<OFMessage> msgs);
+
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriverFactory.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriverFactory.java
new file mode 100644
index 0000000..4e84d28
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/OpenFlowSwitchDriverFactory.java
@@ -0,0 +1,24 @@
+package org.onlab.onos.of.controller.driver;
+
+import org.onlab.onos.of.controller.Dpid;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+/**
+ * Switch factory which returns concrete switch objects for the
+ * physical openflow switch in use.
+ *
+ */
+public interface OpenFlowSwitchDriverFactory {
+
+
+    /**
+     * Constructs the real openflow switch representation.
+     * @param dpid the dpid for this switch.
+     * @param desc its description.
+     * @param ofv the OF version in use
+     * @return the openflow switch representation.
+     */
+    public OpenFlowSwitchDriver getOFSwitchImpl(Dpid dpid,
+            OFDescStatsReply desc, OFVersion ofv);
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleHandler.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleHandler.java
new file mode 100644
index 0000000..bfded52
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleHandler.java
@@ -0,0 +1,94 @@
+package org.onlab.onos.of.controller.driver;
+
+import java.io.IOException;
+
+import org.onlab.onos.of.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFRoleReply;
+
+/**
+ * Role handling.
+ *
+ */
+public interface RoleHandler {
+
+    /**
+     * 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 experimenterMsg 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.
+     */
+    public RoleState extractNiciraRoleReply(OFExperimenter experimenterMsg)
+            throws SwitchStateException;
+
+    /**
+     * 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
+     * @return false if and only if the switch does not support role-request
+     * messages, according to the switch driver; true otherwise.
+     */
+    public boolean sendRoleRequest(RoleState role, RoleRecvStatus exp)
+            throws IOException;
+
+    /**
+     * Extract the role information from an OF1.3 Role Reply Message.
+     * @param rrmsg role reply message
+     * @return RoleReplyInfo object
+     * @throws SwitchStateException
+     */
+    public RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg)
+            throws SwitchStateException;
+
+    /**
+     * 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 rri information about role-reply in format that
+     *                      controller can understand.
+     * @throws SwitchStateException if no request is pending
+     */
+    public RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
+            throws SwitchStateException;
+
+
+    /**
+     * 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
+     */
+    public RoleRecvStatus deliverError(OFErrorMsg error)
+            throws SwitchStateException;
+
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleRecvStatus.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleRecvStatus.java
new file mode 100644
index 0000000..0a10978
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleRecvStatus.java
@@ -0,0 +1,37 @@
+package org.onlab.onos.of.controller.driver;
+
+/**
+ * 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,
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleReplyInfo.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleReplyInfo.java
new file mode 100644
index 0000000..cc3c483
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/RoleReplyInfo.java
@@ -0,0 +1,27 @@
+package org.onlab.onos.of.controller.driver;
+
+import org.onlab.onos.of.controller.RoleState;
+import org.projectfloodlight.openflow.types.U64;
+
+/**
+ * Helper class returns role reply information in the format understood
+ * by the controller.
+ */
+public class RoleReplyInfo {
+    private final RoleState role;
+    private final U64 genId;
+    private final long xid;
+
+    public 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 + "]";
+    }
+}
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java
new file mode 100644
index 0000000..16ed93a
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java
@@ -0,0 +1,14 @@
+package org.onlab.onos.of.controller.driver;
+
+/**
+ * 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/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeCompleted.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeCompleted.java
new file mode 100644
index 0000000..1c6dac9
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeCompleted.java
@@ -0,0 +1,19 @@
+package org.onlab.onos.of.controller.driver;
+
+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/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeException.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeException.java
new file mode 100644
index 0000000..1c9a710
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeException.java
@@ -0,0 +1,26 @@
+package org.onlab.onos.of.controller.driver;
+
+/**
+ * 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/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeNotStarted.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeNotStarted.java
new file mode 100644
index 0000000..0f34b0e
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeNotStarted.java
@@ -0,0 +1,15 @@
+package org.onlab.onos.of.controller.driver;
+
+/**
+ * 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/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeStateException.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeStateException.java
new file mode 100644
index 0000000..09e737e
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchDriverSubHandshakeStateException.java
@@ -0,0 +1,15 @@
+package org.onlab.onos.of.controller.driver;
+
+/**
+ * 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/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchStateException.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchStateException.java
new file mode 100644
index 0000000..55b12de
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/SwitchStateException.java
@@ -0,0 +1,50 @@
+/**
+ *    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.driver;
+
+/**
+ * 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/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/package-info.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/package-info.java
new file mode 100644
index 0000000..f64ba6c
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/driver/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * OpenFlow controller switch driver API.
+ */
+package org.onlab.onos.of.controller.driver;
diff --git a/openflow/api/src/main/java/org/onlab/onos/of/controller/package-info.java b/openflow/api/src/main/java/org/onlab/onos/of/controller/package-info.java
new file mode 100644
index 0000000..888bcce
--- /dev/null
+++ b/openflow/api/src/main/java/org/onlab/onos/of/controller/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * OpenFlow controller API.
+ */
+package org.onlab.onos.of.controller;