From e63291850fd0795c5700e25e67e5dee89ba54c5f Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Tue, 1 Dec 2015 05:49:27 -0800 Subject: onos commit hash c2999f30c69e50df905a9d175ef80b3f23a98514 Change-Id: I2bb8562c4942b6d6a6d60b663db2e17540477b81 Signed-off-by: Ashlee Young --- .../controller/DefaultOpenFlowPacketContext.java | 182 ++++++++ .../org/onosproject/openflow/controller/Dpid.java | 132 ++++++ .../controller/ExtensionTreatmentInterpreter.java | 58 +++ .../openflow/controller/OpenFlowController.java | 130 ++++++ .../openflow/controller/OpenFlowEventListener.java | 33 ++ .../openflow/controller/OpenFlowOpticalSwitch.java | 23 + .../openflow/controller/OpenFlowPacketContext.java | 90 ++++ .../openflow/controller/OpenFlowSwitch.java | 160 +++++++ .../controller/OpenFlowSwitchListener.java | 58 +++ .../openflow/controller/PacketListener.java | 29 ++ .../openflow/controller/PortDescPropertyType.java | 39 ++ .../onosproject/openflow/controller/RoleState.java | 40 ++ .../openflow/controller/ThirdPartyMessage.java | 74 ++++ .../openflow/controller/WithTypedPorts.java | 45 ++ .../controller/driver/AbstractOpenFlowSwitch.java | 493 +++++++++++++++++++++ .../openflow/controller/driver/OpenFlowAgent.java | 102 +++++ .../controller/driver/OpenFlowSwitchDriver.java | 221 +++++++++ .../driver/OpenFlowSwitchDriverFactory.java | 39 ++ .../openflow/controller/driver/RoleHandler.java | 114 +++++ .../openflow/controller/driver/RoleRecvStatus.java | 52 +++ .../openflow/controller/driver/RoleReplyInfo.java | 48 ++ .../SwitchDriverSubHandshakeAlreadyStarted.java | 29 ++ .../driver/SwitchDriverSubHandshakeCompleted.java | 34 ++ .../driver/SwitchDriverSubHandshakeException.java | 41 ++ .../driver/SwitchDriverSubHandshakeNotStarted.java | 30 ++ .../SwitchDriverSubHandshakeStateException.java | 30 ++ .../controller/driver/SwitchStateException.java | 49 ++ .../openflow/controller/driver/package-info.java | 20 + .../openflow/controller/package-info.java | 20 + .../controller/OpenflowControllerAdapter.java | 89 ++++ 30 files changed, 2504 insertions(+) create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/Dpid.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEventListener.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowPacketContext.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitchListener.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PacketListener.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/PortDescPropertyType.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/RoleState.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/WithTypedPorts.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriverFactory.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleHandler.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleRecvStatus.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/RoleReplyInfo.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeAlreadyStarted.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeCompleted.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeException.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeNotStarted.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchDriverSubHandshakeStateException.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/SwitchStateException.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/package-info.java create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/package-info.java create mode 100644 framework/src/onos/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java (limited to 'framework/src/onos/protocols/openflow/api/src') 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 getSwitches(); + + /** + * Returns all master switches known to this OF controller. + * @return Iterable of dpid elements + */ + Iterable getMasterSwitches(); + + /** + * Returns all equal switches known to this OF controller. + * @return Iterable of dpid elements + */ + Iterable 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. + *

+ * Note: Messages may be silently dropped/lost due to IOExceptions or + * role. If this is a concern, then a caller should use barriers. + *

+ * + * @param msg the message to write + */ + void sendMsg(OFMessage msg); + + /** + * Writes the OFMessage list to the driver. + *

+ * Note: Messages may be silently dropped/lost due to IOExceptions or + * role. If this is a concern, then a caller should use barriers. + *

+ * + * @param msgs the messages to be written + */ + void sendMsg(List 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 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 <. + */ +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 getPortsOf(PortDescPropertyType type); + + /** + * Returns the port property types supported by the driver implementing this + * interface. + * + * @return A set of port property types + */ + Set 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 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> 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 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 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 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 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 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 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 > 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 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; diff --git a/framework/src/onos/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java b/framework/src/onos/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java new file mode 100644 index 00000000..f4fe490f --- /dev/null +++ b/framework/src/onos/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java @@ -0,0 +1,89 @@ +/* + * 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; + +/** + * Test adapter for the OpenFlow controller interface. + */ +public class OpenflowControllerAdapter implements OpenFlowController { + @Override + public Iterable getSwitches() { + return null; + } + + @Override + public Iterable getMasterSwitches() { + return null; + } + + @Override + public Iterable getEqualSwitches() { + return null; + } + + @Override + public OpenFlowSwitch getSwitch(Dpid dpid) { + return null; + } + + @Override + public OpenFlowSwitch getMasterSwitch(Dpid dpid) { + return null; + } + + @Override + public OpenFlowSwitch getEqualSwitch(Dpid dpid) { + return null; + } + + @Override + public void addListener(OpenFlowSwitchListener listener) { + } + + @Override + public void removeListener(OpenFlowSwitchListener listener) { + } + + @Override + public void addPacketListener(int priority, PacketListener listener) { + } + + @Override + public void removePacketListener(PacketListener listener) { + } + + @Override + public void write(Dpid dpid, OFMessage msg) { + } + + @Override + public void processPacket(Dpid dpid, OFMessage msg) { + } + + @Override + public void setRole(Dpid dpid, RoleState role) { + } + + @Override + public void addEventListener(OpenFlowEventListener listener) { + } + + @Override + public void removeEventListener(OpenFlowEventListener listener) { + } +} -- cgit 1.2.3-korg