Added openflow-codec and openflowj_netty from openflowplugin
[openflowjava.git] / third-party / openflowj_netty / src / main / java / org / openflow / protocol / OFError.java
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFError.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFError.java
new file mode 100644 (file)
index 0000000..df7b236
--- /dev/null
@@ -0,0 +1,325 @@
+/**
+*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+*    University
+*
+*    Licensed under the Apache License, Version 2.0 (the "License"); you may
+*    not use this file except in compliance with the License. You may obtain
+*    a copy of the License at
+*
+*         http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+*    License for the specific language governing permissions and limitations
+*    under the License.
+**/
+
+package org.openflow.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.factory.MessageParseException;
+import org.openflow.protocol.factory.OFMessageFactory;
+import org.openflow.protocol.factory.OFMessageFactoryAware;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_error_msg
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+public class OFError extends OFMessage implements OFMessageFactoryAware {
+    public static int MINIMUM_LENGTH = 12;
+
+    public enum OFErrorType {
+        // OFPET_VENDOR_ERROR is an extension that was added in Open vSwitch and isn't
+        // in the OF 1.0 spec, but it was easier to add it here instead of adding
+        // generic support for extensible vendor-defined error messages.
+        // It uses the random value 0xb0c2 to avoid conflicts with other possible new
+        // error types. Support for vendor-defined extended errors has been standardized
+        // in the OF 1.2 spec, so this workaround is only needed for 1.0.
+        OFPET_HELLO_FAILED, OFPET_BAD_REQUEST, OFPET_BAD_ACTION, OFPET_FLOW_MOD_FAILED, OFPET_PORT_MOD_FAILED, OFPET_QUEUE_OP_FAILED, OFPET_VENDOR_ERROR((short)0xb0c2);
+
+        protected short value;
+
+        private OFErrorType() {
+            this.value = (short) this.ordinal();
+        }
+
+        private OFErrorType(short value) {
+            this.value = value;
+        }
+
+        public short getValue() {
+            return value;
+        }
+    }
+
+    public enum OFHelloFailedCode {
+        OFPHFC_INCOMPATIBLE, OFPHFC_EPERM
+    }
+
+    public enum OFBadRequestCode {
+        OFPBRC_BAD_VERSION, OFPBRC_BAD_TYPE, OFPBRC_BAD_STAT, OFPBRC_BAD_VENDOR, OFPBRC_BAD_SUBTYPE, OFPBRC_EPERM, OFPBRC_BAD_LEN, OFPBRC_BUFFER_EMPTY, OFPBRC_BUFFER_UNKNOWN
+    }
+
+    public enum OFBadActionCode {
+        OFPBAC_BAD_TYPE, OFPBAC_BAD_LEN, OFPBAC_BAD_VENDOR, OFPBAC_BAD_VENDOR_TYPE, OFPBAC_BAD_OUT_PORT, OFPBAC_BAD_ARGUMENT, OFPBAC_EPERM, OFPBAC_TOO_MANY, OFPBAC_BAD_QUEUE
+    }
+
+    public enum OFFlowModFailedCode {
+        OFPFMFC_ALL_TABLES_FULL, OFPFMFC_OVERLAP, OFPFMFC_EPERM, OFPFMFC_BAD_EMERG_TIMEOUT, OFPFMFC_BAD_COMMAND, OFPFMFC_UNSUPPORTED
+    }
+
+    public enum OFPortModFailedCode {
+        OFPPMFC_BAD_PORT, OFPPMFC_BAD_HW_ADDR
+    }
+
+    public enum OFQueueOpFailedCode {
+        OFPQOFC_BAD_PORT, OFPQOFC_BAD_QUEUE, OFPQOFC_EPERM
+    }
+
+    protected short errorType;
+    protected short errorCode;
+    protected int vendor;
+    protected int vendorErrorType;
+    protected short vendorErrorCode;
+    protected OFMessageFactory factory;
+    protected byte[] error;
+    protected boolean errorIsAscii;
+
+    public OFError() {
+        super();
+        this.type = OFType.ERROR;
+        this.length = U16.t(MINIMUM_LENGTH);
+    }
+
+    /** convenience constructor */
+    public OFError(OFErrorType errorType) {
+        this();
+        setErrorType(errorType);
+    }
+
+    /**
+     * @return the errorType
+     */
+    public short getErrorType() {
+        return errorType;
+    }
+
+    /**
+     * @param errorType
+     *            the errorType to set
+     */
+    public void setErrorType(short errorType) {
+        this.errorType = errorType;
+    }
+
+    public void setErrorType(OFErrorType type) {
+        this.errorType = type.getValue();
+    }
+
+    /**
+     * @return true if the error is an extended vendor error
+     */
+    public boolean isVendorError() {
+        return errorType == OFErrorType.OFPET_VENDOR_ERROR.getValue();
+    }
+
+    /**
+     * @return the errorCode
+     */
+    public short getErrorCode() {
+        return errorCode;
+    }
+
+    /**
+     * @param errorCode
+     *            the errorCode to set
+     */
+    public void setErrorCode(OFHelloFailedCode code) {
+        this.errorCode = (short) code.ordinal();
+    }
+
+    public void setErrorCode(short errorCode) {
+        this.errorCode = errorCode;
+    }
+
+    public void setErrorCode(OFBadRequestCode code) {
+        this.errorCode = (short) code.ordinal();
+    }
+
+    public void setErrorCode(OFBadActionCode code) {
+        this.errorCode = (short) code.ordinal();
+    }
+
+    public void setErrorCode(OFFlowModFailedCode code) {
+        this.errorCode = (short) code.ordinal();
+    }
+
+    public void setErrorCode(OFPortModFailedCode code) {
+        this.errorCode = (short) code.ordinal();
+    }
+
+    public void setErrorCode(OFQueueOpFailedCode code) {
+        this.errorCode = (short) code.ordinal();
+    }
+
+    public int getVendorErrorType() {
+        return vendorErrorType;
+    }
+
+    public void setVendorErrorType(int vendorErrorType) {
+        this.vendorErrorType = vendorErrorType;
+    }
+
+    public short getVendorErrorCode() {
+        return vendorErrorCode;
+    }
+
+    public void setVendorErrorCode(short vendorErrorCode) {
+        this.vendorErrorCode = vendorErrorCode;
+    }
+
+    public OFMessage getOffendingMsg() throws MessageParseException {
+        // should only have one message embedded; if more than one, just
+        // grab first
+        if (this.error == null)
+            return null;
+        ChannelBuffer errorMsg = ChannelBuffers.wrappedBuffer(this.error);
+        if (factory == null)
+            throw new RuntimeException("MessageFactory not set");
+
+        List<OFMessage> msglist = this.factory.parseMessage(errorMsg);
+        if (msglist == null)
+                return null;
+        return msglist.get(0);
+    }
+
+    /**
+     * Write this offending message into the payload of the Error message
+     *
+     * @param offendingMsg
+     */
+
+    public void setOffendingMsg(OFMessage offendingMsg) {
+        if (offendingMsg == null) {
+            super.setLengthU(MINIMUM_LENGTH);
+        } else {
+            this.error = new byte[offendingMsg.getLengthU()];
+            ChannelBuffer data = ChannelBuffers.wrappedBuffer(this.error);
+            data.writerIndex(0);
+            offendingMsg.writeTo(data);
+            super.setLengthU(MINIMUM_LENGTH + offendingMsg.getLengthU());
+        }
+    }
+
+    public OFMessageFactory getFactory() {
+        return factory;
+    }
+
+    @Override
+    public void setMessageFactory(OFMessageFactory factory) {
+        this.factory = factory;
+    }
+
+    /**
+     * @return the error
+     */
+    public byte[] getError() {
+        return error;
+    }
+
+    /**
+     * @param error
+     *            the error to set
+     */
+    public void setError(byte[] error) {
+        this.error = error;
+    }
+
+    /**
+     * @return the errorIsAscii
+     */
+    public boolean isErrorIsAscii() {
+        return errorIsAscii;
+    }
+
+    /**
+     * @param errorIsAscii
+     *            the errorIsAscii to set
+     */
+    public void setErrorIsAscii(boolean errorIsAscii) {
+        this.errorIsAscii = errorIsAscii;
+    }
+
+    @Override
+    public void readFrom(ChannelBuffer data) {
+        super.readFrom(data);
+        this.errorType = data.readShort();
+        this.errorCode = data.readShort();
+        int dataLength = this.getLengthU() - MINIMUM_LENGTH;
+        if (dataLength > 0) {
+            this.error = new byte[dataLength];
+            data.readBytes(this.error);
+            if (this.errorType == OFErrorType.OFPET_HELLO_FAILED.getValue())
+                this.errorIsAscii = true;
+        }
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer data) {
+        super.writeTo(data);
+        data.writeShort(errorType);
+        data.writeShort(errorCode);
+        if (error != null)
+            data.writeBytes(error);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + Arrays.hashCode(error);
+        result = prime * result + errorCode;
+        result = prime * result + (errorIsAscii ? 1231 : 1237);
+        result = prime * result + errorType;
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (!super.equals(obj))
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        OFError other = (OFError) obj;
+        if (!Arrays.equals(error, other.error))
+            return false;
+        if (errorCode != other.errorCode)
+            return false;
+        if (errorIsAscii != other.errorIsAscii)
+            return false;
+        if (errorType != other.errorType)
+            return false;
+        return true;
+    }
+
+}