Initial opendaylight infrastructure commit!!
[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      * Write this offending message into the payload of the Error message
139      * 
140      * @param offendingMsg
141      */
142
143     public void setOffendingMsg(OFMessage offendingMsg) {
144         if (offendingMsg == null) {
145             super.setLengthU(MINIMUM_LENGTH);
146         } else {
147             this.error = new byte[offendingMsg.getLengthU()];
148             ByteBuffer data = ByteBuffer.wrap(this.error);
149             offendingMsg.writeTo(data);
150             super.setLengthU(MINIMUM_LENGTH + offendingMsg.getLengthU());
151         }
152     }
153
154     public OFMessageFactory getFactory() {
155         return factory;
156     }
157
158     @Override
159     public void setMessageFactory(OFMessageFactory factory) {
160         this.factory = factory;
161     }
162
163     /**
164      * @return the error
165      */
166     public byte[] getError() {
167         return error;
168     }
169
170     /**
171      * @param error
172      *            the error to set
173      */
174     public void setError(byte[] error) {
175         this.error = error;
176     }
177
178     /**
179      * @return the errorIsAscii
180      */
181     public boolean isErrorIsAscii() {
182         return errorIsAscii;
183     }
184
185     /**
186      * @param errorIsAscii
187      *            the errorIsAscii to set
188      */
189     public void setErrorIsAscii(boolean errorIsAscii) {
190         this.errorIsAscii = errorIsAscii;
191     }
192
193     @Override
194     public void readFrom(ByteBuffer data) {
195         super.readFrom(data);
196         this.errorType = data.getShort();
197         this.errorCode = data.getShort();
198         int dataLength = this.getLengthU() - MINIMUM_LENGTH;
199         if (dataLength > 0) {
200             this.error = new byte[dataLength];
201             data.get(this.error);
202             if (this.errorType == OFErrorType.OFPET_HELLO_FAILED.ordinal())
203                 this.errorIsAscii = true;
204         }
205     }
206
207     @Override
208     public void writeTo(ByteBuffer data) {
209         super.writeTo(data);
210         data.putShort(errorType);
211         data.putShort(errorCode);
212         if (error != null)
213             data.put(error);
214     }
215
216     /*
217      * (non-Javadoc)
218      * 
219      * @see java.lang.Object#hashCode()
220      */
221     @Override
222     public int hashCode() {
223         final int prime = 31;
224         int result = super.hashCode();
225         result = prime * result + Arrays.hashCode(error);
226         result = prime * result + errorCode;
227         result = prime * result + (errorIsAscii ? 1231 : 1237);
228         result = prime * result + errorType;
229         return result;
230     }
231
232     /*
233      * (non-Javadoc)
234      * 
235      * @see java.lang.Object#equals(java.lang.Object)
236      */
237     @Override
238     public boolean equals(Object obj) {
239         if (this == obj)
240             return true;
241         if (!super.equals(obj))
242             return false;
243         if (getClass() != obj.getClass())
244             return false;
245         OFError other = (OFError) obj;
246         if (!Arrays.equals(error, other.error))
247             return false;
248         if (errorCode != other.errorCode)
249             return false;
250         if (errorIsAscii != other.errorIsAscii)
251             return false;
252         if (errorType != other.errorType)
253             return false;
254         return true;
255     }
256
257 }