Merge "Declare a property for commons-lang version in poms and use it."
[controller.git] / third-party / openflowj / src / main / java / org / openflow / protocol / OFError.java
1 package org.openflow.protocol;
2
3 import java.nio.ByteBuffer;
4 import java.util.Arrays;
5 import java.util.List;
6
7 import org.openflow.protocol.factory.OFMessageFactory;
8 import org.openflow.protocol.factory.OFMessageFactoryAware;
9 import org.openflow.util.U16;
10
11 /**
12  * Represents an ofp_error_msg
13  * 
14  * @author David Erickson (daviderickson@cs.stanford.edu)
15  * @author Rob Sherwood (rob.sherwood@stanford.edu)
16  */
17 public class OFError extends OFMessage implements OFMessageFactoryAware {
18     public static int MINIMUM_LENGTH = 12;
19
20     public enum OFErrorType {
21         OFPET_HELLO_FAILED, OFPET_BAD_REQUEST, OFPET_BAD_ACTION, OFPET_FLOW_MOD_FAILED, OFPET_PORT_MOD_FAILED, OFPET_QUEUE_OP_FAILED
22     }
23
24     public enum OFHelloFailedCode {
25         OFPHFC_INCOMPATIBLE, OFPHFC_EPERM
26     }
27
28     public enum OFBadRequestCode {
29         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
30     }
31
32     public enum OFBadActionCode {
33         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
34     }
35
36     public enum OFFlowModFailedCode {
37         OFPFMFC_ALL_TABLES_FULL, OFPFMFC_OVERLAP, OFPFMFC_EPERM, OFPFMFC_BAD_EMERG_TIMEOUT, OFPFMFC_BAD_COMMAND, OFPFMFC_UNSUPPORTED
38     }
39
40     public enum OFPortModFailedCode {
41         OFPPMFC_BAD_PORT, OFPPMFC_BAD_HW_ADDR
42     }
43
44     public enum OFQueueOpFailedCode {
45         OFPQOFC_BAD_PORT, OFPQOFC_BAD_QUEUE, OFPQOFC_EPERM
46     }
47
48     protected short errorType;
49     protected short errorCode;
50     protected OFMessageFactory factory;
51     protected byte[] error;
52     protected boolean errorIsAscii;
53
54     public OFError() {
55         super();
56         this.type = OFType.ERROR;
57         this.length = U16.t(MINIMUM_LENGTH);
58     }
59
60     /**
61      * @return the errorType
62      */
63     public short getErrorType() {
64         return errorType;
65     }
66
67     /**
68      * @param errorType
69      *            the errorType to set
70      */
71     public void setErrorType(short errorType) {
72         this.errorType = errorType;
73     }
74
75     public void setErrorType(OFErrorType type) {
76         this.errorType = (short) type.ordinal();
77     }
78
79     /**
80      * @return the errorCode
81      */
82     public short getErrorCode() {
83         return errorCode;
84     }
85
86     /**
87      * @param errorCode
88      *            the errorCode to set
89      */
90     public void setErrorCode(OFHelloFailedCode code) {
91         this.errorCode = (short) code.ordinal();
92     }
93
94     public void setErrorCode(short errorCode) {
95         this.errorCode = errorCode;
96     }
97
98     public void setErrorCode(OFBadRequestCode code) {
99         this.errorCode = (short) code.ordinal();
100     }
101
102     public void setErrorCode(OFBadActionCode code) {
103         this.errorCode = (short) code.ordinal();
104     }
105
106     public void setErrorCode(OFFlowModFailedCode code) {
107         this.errorCode = (short) code.ordinal();
108     }
109
110     public void setErrorCode(OFPortModFailedCode code) {
111         this.errorCode = (short) code.ordinal();
112     }
113
114     public void setErrorCode(OFQueueOpFailedCode code) {
115         this.errorCode = (short) code.ordinal();
116     }
117
118     public OFMessage getOffendingMsg() {
119         // should only have one message embedded; if more than one, just
120         // grab first
121         if (this.error == null)
122             return null;
123         ByteBuffer errorMsg = ByteBuffer.wrap(this.error);
124         if (factory == null)
125             throw new RuntimeException("MessageFactory not set");
126         List<OFMessage> messages = this.factory.parseMessages(errorMsg,
127                 error.length);
128         // OVS apparently sends partial messages in errors
129         // need to be careful of that AND can't use data.limit() as
130         // a packet boundary because there could be more data queued
131         if (messages.size() > 0) {
132             return messages.get(0);
133         } else {
134             return null;
135         }
136     }
137
138     /**
139      * Write this offending message into the payload of the Error message
140      * 
141      * @param offendingMsg
142      */
143
144     public void setOffendingMsg(OFMessage offendingMsg) {
145         if (offendingMsg == null) {
146             super.setLengthU(MINIMUM_LENGTH);
147         } else {
148             this.error = new byte[offendingMsg.getLengthU()];
149             ByteBuffer data = ByteBuffer.wrap(this.error);
150             offendingMsg.writeTo(data);
151             super.setLengthU(MINIMUM_LENGTH + offendingMsg.getLengthU());
152         }
153     }
154
155     public OFMessageFactory getFactory() {
156         return factory;
157     }
158
159     @Override
160     public void setMessageFactory(OFMessageFactory factory) {
161         this.factory = factory;
162     }
163
164     /**
165      * @return the error
166      */
167     public byte[] getError() {
168         return error;
169     }
170
171     /**
172      * @param error
173      *            the error to set
174      */
175     public void setError(byte[] error) {
176         this.error = error;
177     }
178
179     /**
180      * @return the errorIsAscii
181      */
182     public boolean isErrorIsAscii() {
183         return errorIsAscii;
184     }
185
186     /**
187      * @param errorIsAscii
188      *            the errorIsAscii to set
189      */
190     public void setErrorIsAscii(boolean errorIsAscii) {
191         this.errorIsAscii = errorIsAscii;
192     }
193
194     @Override
195     public void readFrom(ByteBuffer data) {
196         super.readFrom(data);
197         this.errorType = data.getShort();
198         this.errorCode = data.getShort();
199         int dataLength = this.getLengthU() - MINIMUM_LENGTH;
200         if (dataLength > 0) {
201             this.error = new byte[dataLength];
202             data.get(this.error);
203             if (this.errorType == OFErrorType.OFPET_HELLO_FAILED.ordinal())
204                 this.errorIsAscii = true;
205         }
206     }
207
208     @Override
209     public void writeTo(ByteBuffer data) {
210         super.writeTo(data);
211         data.putShort(errorType);
212         data.putShort(errorCode);
213         if (error != null)
214             data.put(error);
215     }
216
217     /*
218      * (non-Javadoc)
219      * 
220      * @see java.lang.Object#hashCode()
221      */
222     @Override
223     public int hashCode() {
224         final int prime = 31;
225         int result = super.hashCode();
226         result = prime * result + Arrays.hashCode(error);
227         result = prime * result + errorCode;
228         result = prime * result + (errorIsAscii ? 1231 : 1237);
229         result = prime * result + errorType;
230         return result;
231     }
232
233     /*
234      * (non-Javadoc)
235      * 
236      * @see java.lang.Object#equals(java.lang.Object)
237      */
238     @Override
239     public boolean equals(Object obj) {
240         if (this == obj)
241             return true;
242         if (!super.equals(obj))
243             return false;
244         if (getClass() != obj.getClass())
245             return false;
246         OFError other = (OFError) obj;
247         if (!Arrays.equals(error, other.error))
248             return false;
249         if (errorCode != other.errorCode)
250             return false;
251         if (errorIsAscii != other.errorIsAscii)
252             return false;
253         if (errorType != other.errorType)
254             return false;
255         return true;
256     }
257
258 }