Low level openflow drivers have been promoted to the driver subsystem.

All new device drivers should provide a handshaking behaviour as well
as well as a pipeline behaviour.

Change-Id: I883830b074e5d254a8cc6100e6c4fa0023594a36
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
index 89ac278..5a89543 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
@@ -15,12 +15,11 @@
  */
 package org.onosproject.openflow.controller;
 
-import java.util.List;
-
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
-import org.projectfloodlight.openflow.types.TableId;
+
+import java.util.List;
 
 /**
  * Represents to provider facing side of a switch.
@@ -28,38 +27,6 @@
 public interface OpenFlowSwitch {
 
     /**
-     * The TableType is used to determine in which table (TableID) each flow rule
-     * needs to be put for multi-table support switch.
-     * It is used only for multi-table support switch.
-     */
-    public static enum TableType {
-        /* VLAN-to-MPLS table */
-        VLAN_MPLS,
-
-        /* VLAN table */
-        VLAN,
-
-        /* Ethertype table */
-        ETHER,
-
-        /* Class of Service table */
-        COS,
-
-        /* IP table */
-        IP,
-        /* MPLS table */
-        MPLS,
-        /* ACL table */
-        ACL,
-        /* Single table */
-        NONE,
-        /* First table in multi-table */
-        FIRST,
-
-
-    }
-
-    /**
      * Writes the message to the driver.
      *
      * @param msg the message to write
@@ -74,17 +41,6 @@
     public void sendMsg(List<OFMessage> msgs);
 
     /**
-     * Transforms FlowMod messages by setting the correct table-ids and sending
-     * them to the switch. TableType is used to determine the table ID for the OFMessage.
-     * Switch drivers that supports multi-table pipelines should implement this
-     * method.
-     *
-     * @param msg the message to be written
-     * @param tableType the type of table in which the FlowMods need to be inserted
-     */
-    public void transformAndSendMsg(OFMessage msg, TableType tableType);
-
-    /**
      * Handle a message from the switch.
      * @param fromSwitch the message to handle
      */
@@ -192,12 +148,4 @@
      * @return string representation of the connection to the device
      */
     public String channelId();
-
-    /**
-     * Returns the TableType corresponding to the TableId used to identify
-     * a table in an OpenFlow switch.
-     * @param tid identifies a table in an OpenFlow switch using TableId
-     * @return TableType corresponding to 'tid' identifying the type of table
-     */
-    public TableType getTableType(TableId tid);
 }
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index ebfa635..56d88b5 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -20,6 +20,7 @@
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -27,6 +28,7 @@
 
 import org.jboss.netty.channel.Channel;
 import org.onlab.packet.IpAddress;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.openflow.controller.Dpid;
 import org.onosproject.openflow.controller.RoleState;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
@@ -36,10 +38,12 @@
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
 import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleRequest;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFPortStatus;
 import org.projectfloodlight.openflow.protocol.OFRoleReply;
+import org.projectfloodlight.openflow.protocol.OFRoleRequest;
 import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,18 +52,19 @@
  * 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 {
+public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
+        implements OpenFlowSwitchDriver {
 
     protected final Logger log = LoggerFactory.getLogger(getClass());
 
     private static final String SHUTDOWN_MSG = "Worker has already been shutdown";
 
-    protected Channel channel;
+    private Channel channel;
     protected String channelId;
 
     private boolean connected;
     protected boolean startDriverHandshakeCalled = false;
-    private final Dpid dpid;
+    private Dpid dpid;
     private OpenFlowAgent agent;
     private final AtomicInteger xidCounter = new AtomicInteger(0);
 
@@ -76,17 +81,11 @@
     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) {
+    @Override
+    public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
         this.dpid = dpid;
         this.desc = desc;
+        this.ofVersion = ofv;
     }
 
     //************************
@@ -102,7 +101,7 @@
     public final void sendMsg(OFMessage m) {
         if (role == RoleState.MASTER) {
             try {
-                this.write(m);
+                channel.write(Collections.singletonList(m));
             } catch (RejectedExecutionException e) {
                 log.warn(e.getMessage());
                 if (!e.getMessage().contains(SHUTDOWN_MSG)) {
@@ -116,7 +115,7 @@
     public final void sendMsg(List<OFMessage> msgs) {
         if (role == RoleState.MASTER) {
             try {
-                this.write(msgs);
+                channel.write(msgs);
             } catch (RejectedExecutionException e) {
                 log.warn(e.getMessage());
                 if (!e.getMessage().contains(SHUTDOWN_MSG)) {
@@ -127,10 +126,15 @@
     }
 
     @Override
-    public abstract void write(OFMessage msg);
-
-    @Override
-    public abstract void write(List<OFMessage> msgs);
+    public final void sendRoleRequest(OFMessage msg) {
+        if (msg instanceof OFRoleRequest ||
+                msg instanceof OFNiciraControllerRoleRequest) {
+            channel.write(Collections.singletonList(msg));
+            return;
+        }
+        throw new IllegalArgumentException("Someone is trying to send " +
+                                                   "a non role request message");
+    }
 
     @Override
     public final boolean isConnected() {
@@ -418,11 +422,20 @@
         return this.desc.getSerialNum();
     }
 
+
     @Override
     public boolean isOptical() {
         return false;
     }
 
 
+    @Override
+    public String toString() {
+        return this.getClass().getName() + " [" + ((channel != null)
+                ? channel.getRemoteAddress() : "?")
+                + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
+    }
+
+
 
 }
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
index a83b608..365f525 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
@@ -15,9 +15,9 @@
  */
 package org.onosproject.openflow.controller.driver;
 
-import java.util.List;
-
 import org.jboss.netty.channel.Channel;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.openflow.controller.Dpid;
 import org.onosproject.openflow.controller.OpenFlowSwitch;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFErrorMsg;
@@ -26,12 +26,14 @@
 import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFVersion;
 
+import java.util.List;
+
 /**
  * Represents the driver side of an OpenFlow switch.
  * This interface should never be exposed to consumers.
  *
  */
-public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
+public interface OpenFlowSwitchDriver extends OpenFlowSwitch, HandlerBehaviour {
 
     /**
      * Sets the OpenFlow agent to be used. This method
@@ -79,23 +81,6 @@
     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.
      */
@@ -162,12 +147,6 @@
 
 
     /**
-     * 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.
      */
@@ -193,19 +172,42 @@
     public void setConnected(boolean connected);
 
     /**
-     * Writes the message to the output stream
-     * in a driver specific manner.
-     *
-     * @param msg the message to write
+     * Initialises the behaviour.
+     * @param dpid a dpid
+     * @param desc a switch description
+     * @param ofv OpenFlow version
      */
-    public void write(OFMessage msg);
+    void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv);
 
     /**
-     * Writes to the OFMessage list to the output stream
-     * in a driver specific manner.
-     *
-     * @param msgs the messages to be written
+     * Does this switch support Nicira Role messages.
+     * @return true if supports, false otherwise.
      */
-    public void write(List<OFMessage> msgs);
+    Boolean supportNxRole();
+
+
+    /**
+     * Starts the driver specific handshake process.
+     */
+    void startDriverHandshake();
+
+    /**
+     * Checks whether the driver specific handshake is complete.
+     * @return true is finished, false if not.
+     */
+    boolean isDriverHandshakeComplete();
+
+    /**
+     * Process a message during the driver specific handshake.
+     * @param m the message to process.
+     */
+    void processDriverHandshakeMessage(OFMessage m);
+
+    /**
+     * Sends only role request messages.
+     *
+     * @param message a role request message.
+     */
+    void sendRoleRequest(OFMessage message);
 
 }