1 package org.openflow.codec.protocol;
3 import java.io.Serializable;
4 import java.util.HashMap;
7 import org.openflow.codec.io.IDataBuffer;
10 * Represents an ofp_match structure
15 public class OFPMatch implements Cloneable, Serializable {
19 private static final long serialVersionUID = 1L;
20 private static final short MINIMUM_LENGTH = 4;
22 * Match size should be multiple of eight, so padding will be done based on
25 private static final int MULTIPLE_OF_EIGHT = 8;
27 private OFPMatchType matchType;
29 private Map<String, OXMField> fieldMap;
35 matchType = OFPMatchType.OFPMT_OXM;
36 setLength(MINIMUM_LENGTH); // all match fields are wild card
37 fieldMap = new HashMap<String, OXMField>();
45 public void addMatchField(OXMField matchField) {
46 fieldMap.put(matchField.getMatchField().name(), matchField);
55 public void removeMatchField(OXMField matchField) {
56 fieldMap.remove(matchField.getMatchField().name());
60 * get the length OFPMatch TLV
64 public short getLength() {
65 length = OFPMatch.MINIMUM_LENGTH;
66 for (Map.Entry<String, OXMField> entry : fieldMap.entrySet()) {
67 length += entry.getValue().getLength();
73 * get the length OFPMatch TLV
77 public short getLengthWithPadding() {
78 int matchLength = getLength();
79 int paddingLength = ((matchLength % MULTIPLE_OF_EIGHT) == 0) ? 0
80 : (MULTIPLE_OF_EIGHT - (matchLength % MULTIPLE_OF_EIGHT));
81 length = (short) (matchLength + paddingLength);
86 * set the length of OFPMatch TLV
90 public void setLength(short length) {
95 * get the matchfield map
99 public Map<String, OXMField> getMatchFieldMap() {
104 * set the matchfield map
108 public void setMatchFieldMap(Map<String, OXMField> fieldMap) {
109 this.fieldMap = fieldMap;
113 * Read this match from the specified DataBuffer
116 * - data to read to construct match object
117 * @return true - reading is successful , false - failed to read as data is
118 * not proper or prerequisite is not matched
120 public boolean readFrom(IDataBuffer data) {
121 boolean result = false;
122 this.matchType = OFPMatchType.valueOf(data.getShort());
123 // check for valid match type
124 // if not match then either match type is deprecated or not supported
125 if (matchType == OFPMatchType.OFPMT_OXM) {
126 int length = data.getShort();
127 if (length >= MINIMUM_LENGTH) {
128 // match size will be multiple of 8, so need to handle padding
130 int paddingLength = ((length % MULTIPLE_OF_EIGHT) == 0) ? 0
131 : (MULTIPLE_OF_EIGHT - (length % MULTIPLE_OF_EIGHT));
132 // length = length - MINIMUM_LENGTH - paddingLength;
133 /* length of ofp_match, is excluding the padding */
134 length = length - MINIMUM_LENGTH;
137 OXMField oxmField = new OXMField();
138 if (!oxmField.readFrom(data)) {
139 // data is not valid, so log, move the data pointer and
141 byte[] junkData = new byte[length + paddingLength];
146 length = length - oxmField.getLength();
147 this.addMatchField(oxmField);
148 this.length += oxmField.getLength();
152 // remove padding bytes
153 byte[] pad = new byte[paddingLength];
155 // result = MatchUtil.hasPrerequisite(this);
163 * Write this match binary format to the specified DataBuffer
167 public void writeTo(IDataBuffer data) {
168 // TBD - we should proceed if prerequisite matching
169 // MatchUtil.hasPrerequisite(this);
170 data.putShort(matchType.getMatchTypeValue());
171 data.putShort(getLength());
172 for (Map.Entry<String, OXMField> entry : fieldMap.entrySet()) {
173 OXMField field = entry.getValue();
176 // match size should be multiple of 8, so need to handle padding if any
177 int paddingLength = ((getLength() % MULTIPLE_OF_EIGHT) == 0) ? 0
178 : (MULTIPLE_OF_EIGHT - (getLength() % MULTIPLE_OF_EIGHT));
180 byte[] pad = new byte[paddingLength];
186 * create the clone of this OFPMatch
190 public OFPMatch clone() {
192 OFPMatch clonedOFMatch = (OFPMatch) super.clone();
193 clonedOFMatch.fieldMap = new HashMap<String, OXMField>();
194 for (Map.Entry<String, OXMField> entry : fieldMap.entrySet()) {
195 clonedOFMatch.fieldMap.put(entry.getKey(), entry.getValue().clone());
197 return clonedOFMatch;
198 } catch (CloneNotSupportedException e) {
199 throw new RuntimeException(e);
204 * to get the object hashcode
208 public int hashCode() {
209 final int prime = 722;
210 int result = prime + this.getLength();
211 result = prime * result + this.matchType.getMatchTypeValue();
212 result = prime * result + this.fieldMap.hashCode();
217 * to check object equality
219 public boolean equals(Object obj) {
226 if (!(obj instanceof OFPMatch)) {
229 OFPMatch other = (OFPMatch) obj;
230 if (this.matchType != other.matchType) {
233 if (this.getLength() != other.getLength()) {
237 if (!this.fieldMap.equals(other.fieldMap)) {
245 * String representation of Match object ex: OFPMatch[MatchType=OFPMT_OXM,
246 * Length=12, Match Fields[Type=OPENFLOW_BASIC-IPV4_SRC, Length=8, Value=[1,
249 public String toString() {
250 StringBuffer buffer = new StringBuffer();
251 buffer.append("OFPMatch[");
252 buffer.append("MatchType=").append(matchType);
253 buffer.append(", Length=").append(getLength());
254 buffer.append(", Match Fields[");
255 int index = fieldMap.size();
256 for (Map.Entry<String, OXMField> entry : fieldMap.entrySet()) {
257 OXMField field = entry.getValue();
258 buffer.append(field.toString());
264 return buffer.toString();