aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/protocols/openflow/api/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/protocols/openflow/api/src/main/java')
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java182
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/Dpid.java132
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java58
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java130
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEventListener.java33
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java23
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java90
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java160
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitchListener.java58
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PacketListener.java29
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PortDescPropertyType.java39
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/RoleState.java40
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java74
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/WithTypedPorts.java45
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java493
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java102
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java221
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriverFactory.java39
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleHandler.java114
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleRecvStatus.java52
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleReplyInfo.java48
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java29
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeCompleted.java34
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeException.java41
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeNotStarted.java30
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeStateException.java30
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchStateException.java49
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/package-info.java20
-rw-r--r--framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/package-info.java20
29 files changed, 2415 insertions, 0 deletions
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
new file mode 100644
index 00000000..af92a1d0
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+import org.onlab.packet.DeserializationException;
+import org.onlab.packet.Ethernet;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.BufferUnderflowException;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.onosproject.security.AppGuard.checkPermission;
+import static org.onosproject.security.AppPermission.Type.*;
+
+
+/**
+ * Default implementation of an OpenFlowPacketContext.
+ */
+public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
+
+ 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 final boolean isBuffered;
+
+ private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
+ this.sw = s;
+ this.pktin = pkt;
+ this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
+ }
+
+ @Override
+ public void send() {
+ checkPermission(PACKET_WRITE);
+
+ 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(pktinInPort())
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setData(pktin.getData())
+// .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(pktinInPort())
+ .setActions(Collections.singletonList(act))
+ .setData(ethFrame.serialize())
+ .build();
+ }
+
+ @Override
+ public Ethernet parsed() {
+ checkPermission(PACKET_READ);
+
+ try {
+ return Ethernet.deserializer().deserialize(pktin.getData(), 0, pktin.getData().length);
+ } catch (BufferUnderflowException | NullPointerException |
+ DeserializationException e) {
+ Logger log = LoggerFactory.getLogger(getClass());
+ log.error("packet deserialization problem : {}", e.getMessage());
+ return null;
+ }
+ }
+
+ @Override
+ public Dpid dpid() {
+ checkPermission(PACKET_READ);
+
+ return new Dpid(sw.getId());
+ }
+
+ /**
+ * Creates an OpenFlow packet context based on a packet-in.
+ *
+ * @param s OpenFlow switch
+ * @param pkt OpenFlow packet-in
+ * @return the OpenFlow packet context
+ */
+ public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
+ OFPacketIn pkt) {
+ return new DefaultOpenFlowPacketContext(s, pkt);
+ }
+
+ @Override
+ public Integer inPort() {
+ checkPermission(PACKET_READ);
+
+ return pktinInPort().getPortNumber();
+ }
+
+ private OFPort pktinInPort() {
+ if (pktin.getVersion() == OFVersion.OF_10) {
+ return pktin.getInPort();
+ }
+ return pktin.getMatch().get(MatchField.IN_PORT);
+ }
+
+ @Override
+ public byte[] unparsed() {
+ checkPermission(PACKET_READ);
+
+ 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() {
+ checkPermission(PACKET_WRITE);
+
+ return free.getAndSet(false);
+ }
+
+ @Override
+ public boolean isHandled() {
+ checkPermission(PACKET_READ);
+
+ return !free.get();
+ }
+
+ @Override
+ public boolean isBuffered() {
+ checkPermission(PACKET_READ);
+
+ return isBuffered;
+ }
+
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/Dpid.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/Dpid.java
new file mode 100644
index 00000000..6e0f65be
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/Dpid.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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() {
+ return Long.hashCode(value);
+ }
+
+ /**
+ * 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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java
new file mode 100644
index 00000000..dc57977f
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+
+/**
+ * Interprets extension instructions and converts them to/from OpenFlow objects.
+ */
+@Beta
+public interface ExtensionTreatmentInterpreter extends HandlerBehaviour {
+
+ /**
+ * Returns true if the given extension instruction is supported by this
+ * driver.
+ *
+ * @param extensionTreatmentType extension instruction type
+ * @return true if the instruction is supported, otherwise false
+ */
+ boolean supported(ExtensionTreatmentType extensionTreatmentType);
+
+ /**
+ * Maps an extension instruction to an OpenFlow action.
+ *
+ * @param factory OpenFlow factory
+ * @param extensionTreatment extension instruction
+ * @return OpenFlow action
+ */
+ OFAction mapInstruction(OFFactory factory, ExtensionTreatment extensionTreatment);
+
+ /**
+ * Maps an OpenFlow action to an extension instruction.
+ *
+ * @param action OpenFlow action
+ * @return extension instruction
+ */
+ ExtensionTreatment mapAction(OFAction action);
+
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java
new file mode 100644
index 00000000..2c68fa0b
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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
+ */
+ Iterable<OpenFlowSwitch> getSwitches();
+
+ /**
+ * Returns all master switches known to this OF controller.
+ * @return Iterable of dpid elements
+ */
+ Iterable<OpenFlowSwitch> getMasterSwitches();
+
+ /**
+ * Returns all equal switches known to this OF controller.
+ * @return Iterable of dpid elements
+ */
+ Iterable<OpenFlowSwitch> getEqualSwitches();
+
+
+ /**
+ * Returns the actual switch for the given Dpid.
+ * @param dpid the switch to fetch
+ * @return the interface to this switch
+ */
+ 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
+ */
+ 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
+ */
+ OpenFlowSwitch getEqualSwitch(Dpid dpid);
+
+ /**
+ * Register a listener for meta events that occur to OF
+ * devices.
+ * @param listener the listener to notify
+ */
+ void addListener(OpenFlowSwitchListener listener);
+
+ /**
+ * Unregister a listener.
+ *
+ * @param listener the listener to unregister
+ */
+ 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
+ */
+ void addPacketListener(int priority, PacketListener listener);
+
+ /**
+ * Unregister a listener.
+ *
+ * @param listener the listener to unregister
+ */
+ void removePacketListener(PacketListener listener);
+
+ /**
+ * Register a listener for OF msg events.
+ *
+ * @param listener the listener to notify
+ */
+ void addEventListener(OpenFlowEventListener listener);
+
+ /**
+ * Unregister a listener.
+ *
+ * @param listener the listener to unregister
+ */
+ void removeEventListener(OpenFlowEventListener listener);
+
+ /**
+ * Send a message to a particular switch.
+ * @param dpid the switch to send to.
+ * @param msg the message to send
+ */
+ 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.
+ */
+ 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.
+ */
+ void setRole(Dpid dpid, RoleState role);
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEventListener.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEventListener.java
new file mode 100644
index 00000000..5deccf5e
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEventListener.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+
+/**
+ * Notifies providers about openflow msg events.
+ */
+public interface OpenFlowEventListener {
+
+ /**
+ * Handles the message event.
+ *
+ * @param dpid switch data path identifier
+ * @param msg the message
+ */
+ void handleMessage(Dpid dpid, OFMessage msg);
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
new file mode 100644
index 00000000..af678d63
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+/**
+ * A marker interface for optical switches, which require the ability to pass
+ * port information to a Device provider.
+ */
+public interface OpenFlowOpticalSwitch extends OpenFlowSwitch, WithTypedPorts {
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java
new file mode 100644
index 00000000..740d89d0
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+import org.onlab.packet.Ethernet;
+import org.projectfloodlight.openflow.types.OFPort;
+
+/**
+ * A representation of a packet context which allows any provider
+ * to view a packet in event, but may block the response to the
+ * event if blocked has been called. This packet context can be used
+ * to react to the packet in event with a packet out.
+ */
+public interface OpenFlowPacketContext {
+
+ /**
+ * Blocks further responses (ie. send() calls) on this
+ * packet in event.
+ * @return true if blocks
+ */
+ boolean block();
+
+ /**
+ * Checks whether the packet has been handled.
+ * @return true if handled, false otherwise.
+ */
+ boolean isHandled();
+
+ /**
+ * Provided build has been called send the packet
+ * out the switch it came in on.
+ */
+ void send();
+
+ /**
+ * Build the packet out in response to this packet in event.
+ * @param outPort the out port to send to packet out of.
+ */
+ 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.
+ */
+ void build(Ethernet ethFrame, OFPort outPort);
+
+ /**
+ * Provided a handle onto the parsed payload.
+ * @return the parsed form of the payload.
+ */
+ Ethernet parsed();
+
+ /**
+ * Provide an unparsed copy of the data.
+ * @return the unparsed form of the payload.
+ */
+ byte[] unparsed();
+
+ /**
+ * Provide the dpid of the switch where the packet in arrived.
+ * @return the dpid of the switch.
+ */
+ Dpid dpid();
+
+ /**
+ * Provide the port on which the packet arrived.
+ * @return the port
+ */
+ Integer inPort();
+
+ /**
+ * Indicates that this packet is buffered at the switch.
+ * @return buffer indication
+ */
+ boolean isBuffered();
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
new file mode 100644
index 00000000..b6ec5744
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+import org.onosproject.net.Device;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+
+import java.util.List;
+
+/**
+ * Represents to provider facing side of a switch.
+ */
+public interface OpenFlowSwitch {
+
+ /**
+ * Writes the message to the driver.
+ * <p>
+ * Note: Messages may be silently dropped/lost due to IOExceptions or
+ * role. If this is a concern, then a caller should use barriers.
+ * </p>
+ *
+ * @param msg the message to write
+ */
+ void sendMsg(OFMessage msg);
+
+ /**
+ * Writes the OFMessage list to the driver.
+ * <p>
+ * Note: Messages may be silently dropped/lost due to IOExceptions or
+ * role. If this is a concern, then a caller should use barriers.
+ * </p>
+ *
+ * @param msgs the messages to be written
+ */
+ void sendMsg(List<OFMessage> msgs);
+
+ /**
+ * Handle a message from the switch.
+ * @param fromSwitch the message to handle
+ */
+ void handleMessage(OFMessage fromSwitch);
+
+ /**
+ * Sets the role for this switch.
+ * @param role the role to set.
+ */
+ void setRole(RoleState role);
+
+ /**
+ * Fetch the role for this switch.
+ * @return the role.
+ */
+ RoleState getRole();
+
+ /**
+ * Fetches the ports of this switch.
+ * @return unmodifiable list of the ports.
+ */
+ List<OFPortDesc> getPorts();
+
+ /**
+ * Provides the factory for this OF version.
+ * @return OF version specific factory.
+ */
+ OFFactory factory();
+
+ /**
+ * Gets a string version of the ID for this switch.
+ *
+ * @return string version of the ID
+ */
+ String getStringId();
+
+ /**
+ * Gets the datapathId of the switch.
+ *
+ * @return the switch dpid in long format
+ */
+ long getId();
+
+ /**
+ * fetch the manufacturer description.
+ * @return the description
+ */
+ String manufacturerDescription();
+
+ /**
+ * fetch the datapath description.
+ * @return the description
+ */
+ String datapathDescription();
+
+ /**
+ * fetch the hardware description.
+ * @return the description
+ */
+ String hardwareDescription();
+
+ /**
+ * fetch the software description.
+ * @return the description
+ */
+ String softwareDescription();
+
+ /**
+ * fetch the serial number.
+ * @return the serial
+ */
+ String serialNumber();
+
+ /**
+ * Checks if the switch is still connected.
+ *
+ * @return whether the switch is still connected
+ */
+ boolean isConnected();
+
+ /**
+ * Disconnects the switch by closing the TCP connection. Results in a call
+ * to the channel handler's channelDisconnected method for cleanup
+ */
+ void disconnectSwitch();
+
+ /**
+ * Notifies the controller that the device has responded to a set-role request.
+ *
+ * @param requested the role requested by the controller
+ * @param response the role set at the device
+ */
+ void returnRoleReply(RoleState requested, RoleState response);
+
+ /**
+ * Returns the switch device type.
+ *
+ * @return device type
+ */
+ Device.Type deviceType();
+
+ /**
+ * Identifies the channel used to communicate with the switch.
+ *
+ * @return string representation of the connection to the device
+ */
+ String channelId();
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitchListener.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitchListener.java
new file mode 100644
index 00000000..2da41335
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitchListener.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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
+ */
+ void switchAdded(Dpid dpid);
+
+ /**
+ * Notify that the switch was removed.
+ * @param dpid the switch where the event occurred.
+ */
+ void switchRemoved(Dpid dpid);
+
+ /**
+ * Notify that the switch has changed in some way.
+ * @param dpid the switch that changed
+ */
+ void switchChanged(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.
+ */
+ void portChanged(Dpid dpid, OFPortStatus status);
+
+ /**
+ * Notify that a role imposed on a switch failed to take hold.
+ *
+ * @param dpid the switch that failed role assertion
+ * @param requested the role controller requested
+ * @param response role reply from the switch
+ */
+ void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response);
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PacketListener.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PacketListener.java
new file mode 100644
index 00000000..817a6cdf
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PacketListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+/**
+ * Notifies providers about Packet in events.
+ */
+public interface PacketListener {
+
+ /**
+ * Handles the packet.
+ *
+ * @param pktCtx the packet context
+ */
+ void handlePacket(OpenFlowPacketContext pktCtx);
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PortDescPropertyType.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PortDescPropertyType.java
new file mode 100644
index 00000000..3a0f1a0d
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PortDescPropertyType.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+/**
+ * Port description property types (OFPPDPT enums) in OF 1.3 &lt;.
+ */
+public enum PortDescPropertyType {
+ ETHERNET(0), /* Ethernet port */
+ OPTICAL(1), /* Optical port */
+ OPTICAL_TRANSPORT(2), /* OF1.3 Optical transport extension */
+ PIPELINE_INPUT(2), /* Ingress pipeline */
+ PIPELINE_OUTPUT(3), /* Egress pipeline */
+ RECIRCULATE(4), /* Recirculation */
+ EXPERIMENTER(0xffff); /* Experimenter-implemented */
+
+ private final int value;
+
+ PortDescPropertyType(int v) {
+ value = v;
+ }
+
+ public int valueOf() {
+ return value;
+ }
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/RoleState.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/RoleState.java
new file mode 100644
index 00000000..b8304f39
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/RoleState.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java
new file mode 100644
index 00000000..59ef33cf
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+import com.google.common.hash.PrimitiveSink;
+/**
+ * Used to support for the third party privacy flow rule.
+ * it implements OFMessage interface to use exist adapter API.
+ */
+public class ThirdPartyMessage implements OFMessage {
+
+ private final byte[] payLoad; //privacy flow rule
+
+ public ThirdPartyMessage(byte[] payLoad) {
+ this.payLoad = payLoad;
+ }
+
+ public byte[] payLoad() {
+ return payLoad;
+ }
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ // Do nothing here for now.
+ }
+
+ @Override
+ public OFVersion getVersion() {
+ // Do nothing here for now.
+ return null;
+ }
+
+ @Override
+ public OFType getType() {
+ // Do nothing here for now.
+ return null;
+ }
+
+ @Override
+ public long getXid() {
+ // Do nothing here for now.
+ return 0;
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer channelBuffer) {
+ // Do nothing here for now.
+ }
+
+ @Override
+ public Builder createBuilder() {
+ // Do nothing here for now.
+ return null;
+ }
+
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/WithTypedPorts.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/WithTypedPorts.java
new file mode 100644
index 00000000..8b82b4a7
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/WithTypedPorts.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller;
+
+import java.util.List;
+import java.util.Set;
+
+import org.projectfloodlight.openflow.protocol.OFObject;
+
+/**
+ * An interface implemented by OpenFlow devices that enables providers to
+ * retrieve ports based on port property.
+ */
+public interface WithTypedPorts {
+
+ /**
+ * Return a list of interfaces (ports) of the type associated with this
+ * OpenFlow switch.
+ *
+ * @param type The port description property type of requested ports
+ * @return A potentially empty list of ports.
+ */
+ List<? extends OFObject> getPortsOf(PortDescPropertyType type);
+
+ /**
+ * Returns the port property types supported by the driver implementing this
+ * interface.
+ *
+ * @return A set of port property types
+ */
+ Set<PortDescPropertyType> getPortTypes();
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
new file mode 100644
index 00000000..c7174192
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller.driver;
+
+import com.google.common.collect.Lists;
+import org.jboss.netty.channel.Channel;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.Device;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.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.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;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+/**
+ * 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 extends AbstractHandlerBehaviour
+ implements OpenFlowSwitchDriver {
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Channel channel;
+ protected String channelId;
+
+ private boolean connected;
+ protected boolean startDriverHandshakeCalled = false;
+ private Dpid dpid;
+ private OpenFlowAgent agent;
+ private final AtomicInteger xidCounter = new AtomicInteger(0);
+
+ private OFVersion ofVersion;
+
+ protected List<OFPortDescStatsReply> ports = new ArrayList<>();
+
+ protected boolean tableFull;
+
+ private RoleHandler roleMan;
+
+ // TODO this is accessed from multiple threads, but volatile may have performance implications
+ protected volatile RoleState role;
+
+ protected OFFeaturesReply features;
+ protected OFDescStatsReply desc;
+
+ private final AtomicReference<List<OFMessage>> messagesPendingMastership
+ = new AtomicReference<>();
+
+ @Override
+ public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
+ this.dpid = dpid;
+ this.desc = desc;
+ this.ofVersion = ofv;
+ }
+
+ //************************
+ // Channel related
+ //************************
+
+ @Override
+ public final void disconnectSwitch() {
+ this.channel.close();
+ }
+
+ @Override
+ public void sendMsg(OFMessage msg) {
+ this.sendMsg(Collections.singletonList(msg));
+ }
+
+ @Override
+ public final void sendMsg(List<OFMessage> msgs) {
+ /*
+ It is possible that in this block, we transition to SLAVE/EQUAL.
+ If this is the case, the supplied messages will race with the
+ RoleRequest message, and they could be rejected by the switch.
+ In the interest of performance, we will not protect this block with
+ a synchronization primitive, because the message would have just been
+ dropped anyway.
+ */
+ if (role == RoleState.MASTER) {
+ // fast path send when we are master
+
+ sendMsgsOnChannel(msgs);
+ return;
+ }
+ // check to see if mastership transition is in progress
+ synchronized (messagesPendingMastership) {
+ /*
+ messagesPendingMastership is used as synchronization variable for
+ all mastership related changes. In this block, mastership (including
+ role update) will have either occurred or not.
+ */
+ if (role == RoleState.MASTER) {
+ // transition to MASTER complete, send messages
+ sendMsgsOnChannel(msgs);
+ return;
+ }
+
+ List<OFMessage> messages = messagesPendingMastership.get();
+ if (messages != null) {
+ // we are transitioning to MASTER, so add messages to queue
+ messages.addAll(msgs);
+ log.debug("Enqueue message for switch {}. queue size after is {}",
+ dpid, messages.size());
+ } else {
+ // not transitioning to MASTER
+ log.warn("Dropping message for switch {} (role: {}, connected: {}): {}",
+ dpid, role, channel.isConnected(), msgs);
+ }
+ }
+ }
+
+ private void sendMsgsOnChannel(List<OFMessage> msgs) {
+ if (channel.isConnected()) {
+ channel.write(msgs);
+ } else {
+ log.warn("Dropping messages for switch {} because channel is not connected: {}",
+ dpid, msgs);
+ }
+ }
+
+ @Override
+ public final void sendRoleRequest(OFMessage msg) {
+ if (msg instanceof OFRoleRequest ||
+ msg instanceof OFNiciraControllerRoleRequest) {
+ sendMsgsOnChannel(Collections.singletonList(msg));
+ return;
+ }
+ throw new IllegalArgumentException("Someone is trying to send " +
+ "a non role request message");
+ }
+
+ @Override
+ public final void sendHandshakeMessage(OFMessage message) {
+ if (!this.isDriverHandshakeComplete()) {
+ sendMsgsOnChannel(Collections.singletonList(message));
+ }
+ }
+
+ @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;
+ final SocketAddress address = channel.getRemoteAddress();
+ if (address instanceof InetSocketAddress) {
+ final InetSocketAddress inetAddress = (InetSocketAddress) address;
+ final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress());
+ if (ipAddress.isIp4()) {
+ channelId = ipAddress.toString() + ':' + inetAddress.getPort();
+ } else {
+ channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort();
+ }
+ }
+ }
+
+ @Override
+ public String channelId() {
+ return channelId;
+ }
+
+ //************************
+ // 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) {
+ if (this.role == RoleState.MASTER || m instanceof OFPortStatus) {
+ 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);
+ synchronized (messagesPendingMastership) {
+ List<OFMessage> messages = messagesPendingMastership.get();
+ if (messages != null) {
+ this.sendMsg(messages);
+ log.debug("Sending {} pending messages to switch {}",
+ messages.size(), dpid);
+ messagesPendingMastership.set(null);
+ }
+ // perform role transition after clearing messages queue
+ this.role = RoleState.MASTER;
+ }
+ }
+
+ @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.add(portDescReply);
+ }
+
+ @Override
+ public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
+ this.ports.addAll(portDescReplies);
+ }
+
+ @Override
+ public void returnRoleReply(RoleState requested, RoleState response) {
+ this.agent.returnRoleReply(dpid, requested, response);
+ }
+
+ @Override
+ public abstract void startDriverHandshake();
+
+ @Override
+ public abstract boolean isDriverHandshakeComplete();
+
+ @Override
+ public abstract void processDriverHandshakeMessage(OFMessage m);
+
+
+ // Role Handling
+
+ @Override
+ public void setRole(RoleState role) {
+ try {
+ if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
+ // perform role transition to SLAVE/EQUAL before sending role request
+ this.role = role;
+ }
+ if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
+ log.debug("Sending role {} to switch {}", role, getStringId());
+ if (role == RoleState.MASTER) {
+ synchronized (messagesPendingMastership) {
+ if (messagesPendingMastership.get() == null) {
+ log.debug("Initializing new message queue for switch {}", dpid);
+ /*
+ The presence of messagesPendingMastership indicates that
+ a switch is currently transitioning to MASTER, but
+ is still awaiting role reply from switch.
+ */
+ messagesPendingMastership.set(Lists.newArrayList());
+ }
+ }
+ }
+ } else if (role == RoleState.MASTER) {
+ // role request not support; transition switch to MASTER
+ this.role = role;
+ }
+ } catch (IOException e) {
+ log.error("Unable to write to switch {}.", this.dpid);
+ }
+ }
+
+ @Override
+ public void reassertRole() {
+ // TODO should messages be sent directly or queue during reassertion?
+ if (this.getRole() == RoleState.MASTER) {
+ log.warn("Received permission error from switch {} while " +
+ "being master. Reasserting master role.",
+ this.getStringId());
+ this.setRole(RoleState.MASTER);
+ }
+ }
+
+ @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.SLAVE) {
+ this.transitionToEqualSwitch();
+ }
+ } else {
+ log.warn("Failed to set role for {}", this.getStringId());
+ }
+ }
+
+ @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);
+ return;
+ }
+
+ 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();
+ }
+ } else {
+ this.disconnectSwitch();
+ }
+ }
+
+ @Override
+ public boolean handleRoleError(OFErrorMsg error) {
+ try {
+ return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
+ } catch (SwitchStateException e) {
+ this.disconnectSwitch();
+ }
+ return true;
+ }
+
+ @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 this.ports.stream()
+ .flatMap(portReply -> portReply.getEntries().stream())
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public String manufacturerDescription() {
+ 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();
+ }
+
+ @Override
+ public Device.Type deviceType() {
+ return Device.Type.SWITCH;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getName() + " [" + ((channel != null)
+ ? channel.getRemoteAddress() : "?")
+ + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
+ }
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java
new file mode 100644
index 00000000..ad6dede1
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller.driver;
+
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.OpenFlowSwitch;
+import org.onosproject.openflow.controller.RoleState;
+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.
+ */
+ 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
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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
+ */
+ void processMessage(Dpid dpid, OFMessage m);
+
+ /**
+ * Notifies the controller that role assertion has failed.
+ *
+ * @param dpid the switch that failed role assertion
+ * @param requested the role controller requested
+ * @param response role reply from the switch
+ */
+ void returnRoleReply(Dpid dpid, RoleState requested, RoleState response);
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
new file mode 100644
index 00000000..b259388c
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller.driver;
+
+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;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+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, HandlerBehaviour {
+
+ /**
+ * Sets the OpenFlow agent to be used. This method
+ * can only be called once.
+ * @param agent the agent to set.
+ */
+ void setAgent(OpenFlowAgent agent);
+
+ /**
+ * Sets the Role handler object.
+ * This method can only be called once.
+ * @param roleHandler the roleHandler class
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ void handleNiciraRole(OFMessage m) throws SwitchStateException;
+
+ /**
+ * Handle OF 1.x (where x &gt; 0) role messages.
+ * @param m the role message to handle
+ * @throws SwitchStateException if the message received was
+ * not a nicira role or was malformed.
+ */
+ void handleRole(OFMessage m) throws SwitchStateException;
+
+ /**
+ * Announce to the OpenFlow agent that this switch has connected.
+ * @return true if successful, false if duplicate switch.
+ */
+ 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.
+ */
+ 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.
+ */
+ boolean activateEqualSwitch();
+
+ /**
+ * Transition this switch-controller relationship to an EQUAL state.
+ */
+ void transitionToEqualSwitch();
+
+ /**
+ * Transition this switch-controller relationship to an Master state.
+ */
+ void transitionToMasterSwitch();
+
+ /**
+ * Remove this switch from the openflow agent.
+ */
+ void removeConnectedSwitch();
+
+ /**
+ * Sets the ports on this switch.
+ * @param portDescReply the port set and descriptions
+ */
+ void setPortDescReply(OFPortDescStatsReply portDescReply);
+
+ /**
+ * Sets the ports on this switch.
+ * @param portDescReplies list of port set and descriptions
+ */
+ void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies);
+
+ /**
+ * Sets the features reply for this switch.
+ * @param featuresReply the features to set.
+ */
+ void setFeaturesReply(OFFeaturesReply featuresReply);
+
+ /**
+ * Sets the switch description.
+ * @param desc the descriptions
+ */
+ void setSwitchDescription(OFDescStatsReply desc);
+
+ /**
+ * Gets the next transaction id to use.
+ * @return the xid
+ */
+ int getNextTransactionId();
+
+
+ /**
+ * Sets the OF version for this switch.
+ * @param ofV the version to set.
+ */
+ void setOFVersion(OFVersion ofV);
+
+ /**
+ * Sets this switch has having a full flowtable.
+ * @param full true if full, false otherswise.
+ */
+ void setTableFull(boolean full);
+
+ /**
+ * Sets the associated Netty channel for this switch.
+ * @param channel the Netty channel
+ */
+ void setChannel(Channel channel);
+
+ /**
+ * Sets whether the switch is connected.
+ *
+ * @param connected whether the switch is connected
+ */
+ void setConnected(boolean connected);
+
+ /**
+ * Initialises the behaviour.
+ * @param dpid a dpid
+ * @param desc a switch description
+ * @param ofv OpenFlow version
+ */
+ void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv);
+
+ /**
+ * Does this switch support Nicira Role messages.
+ * @return true if supports, false otherwise.
+ */
+ 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);
+
+ /**
+ * Allows the handshaker behaviour to send messages during the
+ * handshake phase only.
+ *
+ * @param message an OpenFlow message
+ */
+ void sendHandshakeMessage(OFMessage message);
+
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriverFactory.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriverFactory.java
new file mode 100644
index 00000000..a0d8f18f
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriverFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller.driver;
+
+import org.onosproject.openflow.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.
+ */
+ OpenFlowSwitchDriver getOFSwitchImpl(Dpid dpid,
+ OFDescStatsReply desc, OFVersion ofv);
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleHandler.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleHandler.java
new file mode 100644
index 00000000..b4068886
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleHandler.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller.driver;
+
+import java.io.IOException;
+
+import org.onosproject.openflow.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.
+ */
+ 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 role to request
+ * @param exp expectation
+ * @throws IOException when I/O exception of some sort has occurred
+ * @return false if and only if the switch does not support role-request
+ * messages, according to the switch driver; true otherwise.
+ */
+ 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 If unknown role encountered
+ */
+ 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.
+ * @return result comparing expected and received reply
+ * @throws SwitchStateException if no request is pending
+ */
+ 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
+ * @param error error message
+ * @return result comparing expected and received reply
+ * @throws SwitchStateException if switch did not support requested role
+ */
+ RoleRecvStatus deliverError(OFErrorMsg error)
+ throws SwitchStateException;
+
+}
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleRecvStatus.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleRecvStatus.java
new file mode 100644
index 00000000..88c4cc70
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleRecvStatus.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleReplyInfo.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleReplyInfo.java
new file mode 100644
index 00000000..dc9b6bad
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleReplyInfo.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.controller.driver;
+
+import org.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java
new file mode 100644
index 00000000..96b4bd73
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeCompleted.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeCompleted.java
new file mode 100644
index 00000000..b0f59fe5
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeCompleted.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeException.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeException.java
new file mode 100644
index 00000000..1bc750ab
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeNotStarted.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeNotStarted.java
new file mode 100644
index 00000000..a073683c
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeNotStarted.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeStateException.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeStateException.java
new file mode 100644
index 00000000..3f4be813
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeStateException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchStateException.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchStateException.java
new file mode 100644
index 00000000..30c4e917
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchStateException.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onosproject.openflow.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/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/package-info.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/package-info.java
new file mode 100644
index 00000000..c03a5840
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.
+ */
+
+/**
+ * OpenFlow controller switch driver API.
+ */
+package org.onosproject.openflow.controller.driver;
diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/package-info.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/package-info.java
new file mode 100644
index 00000000..54778426
--- /dev/null
+++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.
+ */
+
+/**
+ * OpenFlow controller API.
+ */
+package org.onosproject.openflow.controller;