54bf43c8bde363065ccab671b75c1eb3745eee11
[openflowjava.git] / third-party / openflow-codec / src / main / java / org / openflow / codec / protocol / OFPErrorMsg.java
1 package org.openflow.codec.protocol;
2
3 import java.util.Arrays;
4 import java.util.List;
5
6 import org.openflow.codec.io.IDataBuffer;
7 import org.openflow.codec.protocol.factory.OFPMessageFactory;
8 import org.openflow.codec.protocol.factory.OFPMessageFactoryAware;
9 import org.openflow.codec.util.U16;
10
11 /**
12  * Represents an ofp_error_msg and also ofp_error_experimenter_msg
13  * 
14  * @author David Erickson (daviderickson@cs.stanford.edu)
15  * @author Rob Sherwood (rob.sherwood@stanford.edu)
16  */
17 public class OFPErrorMsg extends OFPMessage implements OFPMessageFactoryAware
18 {
19         private static int MINIMUM_LENGTH = 12;
20         private static int EXP_MINIMUM_LENGTH = 16;
21
22         // correspond to enum ofp_hello_failed_code
23         public enum OFPHelloFailedCode
24         {
25                 OFPHFC_INCOMPATIBLE, OFPHFC_EPERM
26         }
27
28         // correspond to enum ofp_bad_request_code
29         public enum OFPBadRequestCode
30         {
31                 OFPBRC_BAD_VERSION, OFPBRC_BAD_TYPE, OFPBRC_BAD_MULTIPART, OFPBRC_BAD_EXPERIMENTER, OFPBRC_BAD_EXP_TYPE, OFPBRC_EPERM, OFPBRC_BAD_LEN, OFPBRC_BUFFER_EMPTY, OFPBRC_BUFFER_UNKNOWN, OFPBRC_BAD_TABLE_ID, OFPBRC_IS_SLAVE, OFPBRC_BAD_PORT, OFPBRC_BAD_PACKET, OFPBRC_MULTIPART_BUFFER_OVERFLOW
32         }
33
34         // correspond to enum ofp_bad_action_code
35         public enum OFPBadActionCode
36         {
37                 OFPBAC_BAD_TYPE, OFPBAC_BAD_LEN, OFPBAC_BAD_EXPERIMENTER, OFPBAC_BAD_EXP_TYPE, OFPBAC_BAD_OUT_PORT, OFPBAC_BAD_ARGUMENT, OFPBAC_EPERM, OFPBAC_TOO_MANY, OFPBAC_BAD_QUEUE, OFPBAC_BAD_OUT_GROUP, OFPBAC_MATCH_INCONSISTENT, OFPBAC_UNSUPPORTED_ORDER, OFPBAC_BAD_TAG, OFPBAC_BAD_SET_TYPE, OFPBAC_BAD_SET_LEN, OFPBAC_BAD_SET_ARGUMENT
38         }
39
40         // correspond to enum ofp_bad_instruction_code
41         public enum OFPBadInstructionCode
42         {
43                 OFPBIC_UNKNOWN_INST, OFPBIC_UNSUP_INST, OFPBIC_BAD_TABLE_ID, OFPBIC_UNSUP_METADATA, OFPBIC_UNSUP_METADATA_MASK, OFPBIC_BAD_EXPERIMENTER, OFPBIC_BAD_EXP_TYPE, OFPBIC_BAD_LEN, OFPBIC_EPERM
44         }
45
46         // correspond to enum ofp_bad_match_code
47         public enum OFPBadMatchCode
48         {
49                 OFPBMC_BAD_TYPE, OFPBMC_BAD_LEN, OFPBMC_BAD_TAG, OFPBMC_BAD_DL_ADDR_MASK, OFPBMC_BAD_NW_ADDR_MASK, OFPBMC_BAD_WILDCARDS, OFPBMC_BAD_FIELD, OFPBMC_BAD_VALUE, OFPBMC_BAD_MASK, OFPBMC_BAD_PREREQ, OFPBMC_DUP_FIELD, OFPBMC_EPERM
50
51         }
52
53         // correspond to enum ofp_flow_mod_failed_code
54         public enum OFPFlowModFailedCode
55         {
56                 OFPFMFC_UNKNOWN, OFPFMFC_TABLE_FULL, OFPFMFC_BAD_TABLE_ID, OFPFMFC_OVERLAP, OFPFMFC_EPERM, OFPFMFC_BAD_TIMEOUT, OFPFMFC_BAD_COMMAND, OFPFMFC_BAD_FLAGS
57         }
58
59         // correspond to enum ofp_group_mod_failed_code
60         public enum OFPGroupModFailedCode
61         {
62                 OFPGMFC_GROUP_EXISTS, OFPGMFC_INVALID_GROUP, OFPGMFC_WEIGHT_UNSUPPORTED, OFPGMFC_OUT_OF_GROUPS, OFPGMFC_OUT_OF_BUCKETS, OFPGMFC_CHAINING_UNSUPPORTED, OFPGMFC_WATCH_UNSUPPORTED, OFPGMFC_LOOP, OFPGMFC_UNKNOWN_GROUP, OFPGMFC_CHAINED_GROUP, OFPGMFC_BAD_TYPE, OFPGMFC_BAD_COMMAND, OFPGMFC_BAD_BUCKET, OFPGMFC_BAD_WATCH, OFPGMFC_EPERM
63         }
64
65         // correspond to enum ofp_port_mod_failed_code
66         public enum OFPPortModFailedCode
67         {
68                 OFPPMFC_BAD_PORT, OFPPMFC_BAD_HW_ADDR, OFPPMFC_BAD_CONFIG, OFPPMFC_BAD_ADVERTISE, OFPPMFC_EPERM
69         }
70
71         // correspond to enum ofp_table_mod_failed_code
72         public enum OFPTableModFailedCode
73         {
74                 OFPTMFC_BAD_TABLE, OFPTMFC_BAD_CONFIG, OFPTMFC_EPERM
75         }
76
77         // correspond to enum ofp_queue_op_failed_code
78         public enum OFPQueueOpFailedCode
79         {
80                 OFPQOFC_BAD_PORT, OFPQOFC_BAD_QUEUE, OFPQOFC_EPERM
81         }
82
83         // correspond to enum ofp_switch_config_failed_code
84         public enum OFPSwitchConfigFailedCode
85         {
86                 OFPSCFC_BAD_FLAGS, OFPSCFC_BAD_LEN, OFPSCFC_EPERM
87         }
88
89         // correspond to enum ofp_role_request_failed_code
90         public enum OFPRoleRequestFailedCode
91         {
92                 OFPRRFC_STALE, OFPRRFC_UNSUP, OFPRRFC_BAD_ROLE
93         }
94
95         // correspond to enum ofp_meter_mod_failed_code
96         public enum OFPMeterModFailedCode
97         {
98                 OFPMMFC_UNKNOWN, OFPMMFC_METER_EXISTS, OFPMMFC_INVALID_METER, OFPMMFC_UNKNOWN_METER, OFPMMFC_BAD_COMMAND, OFPMMFC_BAD_FLAGS, OFPMMFC_BAD_RATE, OFPMMFC_BAD_BURST, OFPMMFC_BAD_BAND, OFPMMFC_BAD_BAND_VALUE, OFPMMFC_OUT_OF_METERS, OFPMMFC_OUT_OF_BANDS
99
100         }
101
102         // correspond to enum ofp_table_features_failed_code
103         public enum OFPTableFeaturesFailedCode
104         {
105                 OFPTFFC_BAD_TABLE, OFPTFFC_BAD_METADATA, OFPTFFC_BAD_TYPE, OFPTFFC_BAD_LEN, OFPTFFC_BAD_ARGUMENT, OFPTFFC_EPERM
106         }
107
108         private OFPErrorType errorType;
109         private short errorCode;
110         private byte[] errorData;
111         private short expType;
112         private int experimenter;
113
114         // non-message field
115         private OFPMessageFactory factory;
116         private boolean errorIsAscii;
117
118         public OFPErrorMsg()
119         {
120                 super();
121                 this.type = OFPType.ERROR;
122                 this.length = U16.t(MINIMUM_LENGTH);
123         }
124
125         /**
126          * @return the errorType
127          */
128         public OFPErrorType getErrorType()
129         {
130                 return errorType;
131         }
132
133         /**
134          * @param errorType
135          *            the errorType to set
136          */
137         public void setErrorType(OFPErrorType type)
138         {
139                 this.errorType = type;
140         }
141
142         /**
143          * @return the errorCode
144          */
145         public short getErrorCode()
146         {
147                 return errorCode;
148         }
149
150         public void setErrorCode(short errorCode)
151         {
152                 this.errorCode = errorCode;
153         }
154
155         /**
156          * @param errorCode
157          *            the errorCode to set
158          */
159         public void setErrorCode(OFPHelloFailedCode code)
160         {
161                 this.errorCode = (short) code.ordinal();
162         }
163
164         public void setErrorCode(OFPBadRequestCode code)
165         {
166                 this.errorCode = (short) code.ordinal();
167         }
168
169         public void setErrorCode(OFPBadActionCode code)
170         {
171                 this.errorCode = (short) code.ordinal();
172         }
173
174         public void setErrorCode(OFPFlowModFailedCode code)
175         {
176                 this.errorCode = (short) code.ordinal();
177         }
178
179         public void setErrorCode(OFPPortModFailedCode code)
180         {
181                 this.errorCode = (short) code.ordinal();
182         }
183
184         public void setErrorCode(OFPQueueOpFailedCode code)
185         {
186                 this.errorCode = (short) code.ordinal();
187         }
188
189         public void setErrorCode(OFPBadInstructionCode code)
190         {
191                 this.errorCode = (short) code.ordinal();
192         }
193
194         public void setErrorCode(OFPBadMatchCode code)
195         {
196                 this.errorCode = (short) code.ordinal();
197         }
198
199         public void setErrorCode(OFPGroupModFailedCode code)
200         {
201                 this.errorCode = (short) code.ordinal();
202         }
203
204         public void setErrorCode(OFPTableModFailedCode code)
205         {
206                 this.errorCode = (short) code.ordinal();
207         }
208
209         public void setErrorCode(OFPSwitchConfigFailedCode code)
210         {
211                 this.errorCode = (short) code.ordinal();
212         }
213
214         public void setErrorCode(OFPRoleRequestFailedCode code)
215         {
216                 this.errorCode = (short) code.ordinal();
217         }
218
219         public void setErrorCode(OFPMeterModFailedCode code)
220         {
221                 this.errorCode = (short) code.ordinal();
222         }
223
224         public void setErrorCode(OFPTableFeaturesFailedCode code)
225         {
226                 this.errorCode = (short) code.ordinal();
227         }
228
229         public OFPMessage getOffendingMsg(IDataBuffer data)
230         {
231                 // should only have one message embedded; if more than one, just
232                 // grab first
233                 if (this.errorData == null)
234                         return null;
235                 IDataBuffer errorMsg = data.wrap(this.errorData);
236                 if (factory == null)
237                         throw new RuntimeException("MessageFactory not set");
238                 List<OFPMessage> messages = this.factory.parseMessages(errorMsg,
239                                 errorData.length);
240                 // OVS apparently sends partial messages in errors
241                 // need to be careful of that AND can't use data.limit() as
242                 // a packet boundary because there could be more data queued
243                 if (messages.size() > 0)
244                         return messages.get(0);
245                 else
246                         return null;
247         }
248
249         /**
250          * Write this offending message into the payload of the Error message
251          * 
252          * @param offendingMsg
253          */
254
255         public void setOffendingMsg(OFPMessage offendingMsg, IDataBuffer buffer)
256         {
257                 int minlength = MINIMUM_LENGTH;
258                 if (OFPErrorType.OFPET_EXPERIMENTER.getValue() == this.errorType
259                                 .getValue())
260                 {
261                         minlength = EXP_MINIMUM_LENGTH;
262                 }
263
264                 if (offendingMsg == null)
265                 {
266                         super.setLengthU(minlength);
267                 } else
268                 {
269                         this.errorData = new byte[offendingMsg.getLengthU()];
270                         IDataBuffer data = buffer.wrap(errorData);
271                         offendingMsg.writeTo(data);
272                         super.setLengthU(minlength + offendingMsg.getLengthU());
273                 }
274         }
275
276         public OFPMessageFactory getFactory()
277         {
278                 return factory;
279         }
280
281         @Override
282         public void setMessageFactory(OFPMessageFactory factory)
283         {
284                 this.factory = factory;
285         }
286
287         /**
288          * @return the error
289          */
290         public byte[] getErrorData()
291         {
292                 return errorData;
293         }
294
295         /**
296          * @param error
297          *            the error to set
298          */
299         public void setErrorData(byte[] error)
300         {
301                 this.errorData = error;
302         }
303
304         /**
305          * @return the errorIsAscii
306          */
307         public boolean isErrorIsAscii()
308         {
309                 return errorIsAscii;
310         }
311
312         /**
313          * @param errorIsAscii
314          *            the errorIsAscii to set
315          */
316         public void setErrorIsAscii(boolean errorIsAscii)
317         {
318                 this.errorIsAscii = errorIsAscii;
319         }
320
321         @Override
322         public void readFrom(IDataBuffer data)
323         {
324                 super.readFrom(data);
325                 this.errorType = OFPErrorType.valueOf(data.getShort());
326                 if (this.errorType.getValue() == OFPErrorType.OFPET_EXPERIMENTER
327                                 .getValue())
328                 {
329                         this.expType = data.getShort();
330                         this.experimenter = data.getInt();
331                         int dataLength = this.getLengthU() - EXP_MINIMUM_LENGTH;
332                         if (dataLength > 0)
333                         {
334                                 this.errorData = new byte[dataLength];
335                                 data.get(this.errorData);
336                         }
337                 } else
338                 {
339
340                         this.errorCode = data.getShort();
341                         int dataLength = this.getLengthU() - MINIMUM_LENGTH;
342                         if (dataLength > 0)
343                         {
344                                 this.errorData = new byte[dataLength];
345                                 data.get(this.errorData);
346                                 if (this.errorType.getValue() == OFPErrorType.OFPET_HELLO_FAILED
347                                                 .getValue())
348                                         this.errorIsAscii = true;
349                         }
350                 }
351         }
352
353         @Override
354         public void writeTo(IDataBuffer data)
355         {
356                 if (this.errorType.getValue() == OFPErrorType.OFPET_EXPERIMENTER
357                                 .getValue())
358                 {
359                         this.length = U16.t(EXP_MINIMUM_LENGTH);
360                 }
361                 super.writeTo(data);
362                 data.putShort(errorType.getValue());
363                 if (this.errorType.getValue() == OFPErrorType.OFPET_EXPERIMENTER
364                                 .getValue())
365                 {
366                         data.putShort(expType);
367                         data.putInt(experimenter);
368                 } else
369                 {
370                         data.putShort(errorCode);
371                 }
372                 if (errorData != null)
373                         data.put(errorData);
374         }
375
376         /*
377          * (non-Javadoc)
378          * 
379          * @see java.lang.Object#hashCode()
380          */
381         @Override
382         public int hashCode()
383         {
384                 final int prime = 31;
385                 int result = super.hashCode();
386                 result = prime * result + Arrays.hashCode(errorData);
387                 result = prime * result + errorCode;
388                 result = prime * result + (errorIsAscii ? 1231 : 1237);
389                 result = prime * result + errorType.getValue();
390                 result = prime * result + expType;
391                 result = prime * result + experimenter;
392                 return result;
393         }
394
395         /*
396          * (non-Javadoc)
397          * 
398          * @see java.lang.Object#equals(java.lang.Object)
399          */
400         @Override
401         public boolean equals(Object obj)
402         {
403                 if (this == obj)
404                         return true;
405                 if (!super.equals(obj))
406                         return false;
407                 if (getClass() != obj.getClass())
408                         return false;
409                 OFPErrorMsg other = (OFPErrorMsg) obj;
410                 if (!Arrays.equals(errorData, other.errorData))
411                         return false;
412                 if (errorCode != other.errorCode)
413                         return false;
414                 if (errorIsAscii != other.errorIsAscii)
415                         return false;
416                 if (errorType != other.errorType)
417                         return false;
418                 if (expType != other.expType)
419                         return false;
420                 if (experimenter != other.experimenter)
421                         return false;
422                 return true;
423         }
424
425         /**
426          * get experimenter type
427          * 
428          * @return
429          */
430         public short getExpType()
431         {
432                 return expType;
433         }
434
435         /**
436          * set experimenter type
437          * 
438          * @param expType
439          */
440         public void setExpType(short expType)
441         {
442                 this.expType = expType;
443         }
444
445         /**
446          * get experimenter Id
447          * 
448          * @return
449          */
450         public int getExperimenter()
451         {
452                 return experimenter;
453         }
454
455         /**
456          * set experimenter id
457          * 
458          * @param experimenter
459          */
460         public void setExperimenter(int experimenter)
461         {
462                 this.experimenter = experimenter;
463         }
464
465 }