Mark AD-SAL interfaces as deprecated
[controller.git] / opendaylight / adsal / sal / api / src / main / java / org / opendaylight / controller / sal / match / MatchType.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.sal.match;
10
11 import java.net.Inet4Address;
12 import java.net.InetAddress;
13 import java.util.Arrays;
14
15 import org.opendaylight.controller.sal.core.NodeConnector;
16 import org.opendaylight.controller.sal.utils.HexEncode;
17 import org.opendaylight.controller.sal.utils.NetUtils;
18
19 /**
20  * Represents the binding between the id, the value and mask type and the range
21  * values of the elements type that can be matched on the network
22  * frame/packet/message
23  */
24 @Deprecated
25 public enum MatchType {
26     IN_PORT("inPort", 1 << 0, NodeConnector.class, 1, 0),
27     DL_SRC("dlSrc", 1 << 1, Byte[].class, 0, 0xffffffffffffL),
28     DL_DST("dlDst", 1 << 2, Byte[].class, 0, 0xffffffffffffL),
29     DL_VLAN("dlVlan", 1 << 3, Short.class, 0, 0xfff), // 2 bytes
30     DL_VLAN_PR("dlVlanPriority", 1 << 4, Byte.class, 0, 0x7), // 3 bits
31     DL_OUTER_VLAN("dlOuterVlan", 1 << 5, Short.class, 1, 0xfff),
32     DL_OUTER_VLAN_PR("dlOuterVlanPriority", 1 << 6, Short.class, 0, 0x7),
33     DL_TYPE("dlType", 1 << 7, Short.class, 0, 0xffff), // 2 bytes
34     NW_TOS("nwTOS", 1 << 8, Byte.class, 0, 0x3f), // 6 bits (DSCP field)
35     NW_PROTO("nwProto", 1 << 9, Byte.class, 0, 0xff), // 1 byte
36     NW_SRC("nwSrc", 1 << 10, InetAddress.class, 0, 0),
37     NW_DST("nwDst", 1 << 11, InetAddress.class, 0, 0),
38     TP_SRC("tpSrc", 1 << 12, Short.class, 0, 0xffff), // 2 bytes
39     TP_DST("tpDst", 1 << 13, Short.class, 0, 0xffff); // 2 bytes
40
41     // Used to indicate that no VLAN ID is set.
42     public static final short DL_VLAN_NONE = (short) 0;
43
44     private String id;
45     private int index;
46     private Class<?> dataType;
47     private long minValue;
48     private long maxValue;
49
50     private MatchType(String id, int index, Class<?> dataType, long minValue, long maxValue) {
51         this.id = id;
52         this.index = index;
53         this.dataType = dataType;
54         this.minValue = minValue;
55         this.maxValue = maxValue;
56     }
57
58     public String id() {
59         return id;
60     }
61
62     public int getIndex() {
63         return index;
64     }
65
66     public Class<?> dataType() {
67         return dataType;
68     }
69
70     public String getRange() {
71         return "[0x" + Long.toHexString(minValue) + "-0x" + Long.toHexString(maxValue) + "]";
72     }
73
74     /**
75      * Perform the assignment type validation
76      *
77      * @param value
78      * @param mask
79      * @return
80      */
81     public boolean isCongruentType(Object value, Object mask) {
82         // Mask type has to match value type
83         if (mask != null && (mask.getClass() != value.getClass())) {
84             return false;
85         }
86
87         Class<?> e = this.dataType();
88         Class<?> g = value.getClass();
89
90         // This is all what we need, if value type is same of match required
91         // type
92         if (g.equals(e)) {
93             return true;
94         }
95
96         // This is for the numeric class vs primitive congruence
97         // For what concerns here, for instance, Integer is congruent to int
98         if (e == Short.class) {
99             return g.equals(short.class);
100         }
101
102         if (e == Integer.class) {
103             return g.equals(int.class);
104         }
105
106         if (e == Byte.class) {
107             return g.equals(byte.class);
108         }
109
110         if (e == Byte[].class) {
111             return g.equals(byte[].class);
112         }
113
114         if (e == InetAddress.class) {
115             return g.getSuperclass().equals(InetAddress.class);
116         }
117         return false;
118     }
119
120     /**
121      * Perform the value and mask range validation
122      *
123      * @param value
124      * @param mask
125      * @return
126      */
127     public boolean isValid(Object value, Object mask) {
128         // Skip if main error
129         if (mask != null && (mask.getClass() != value.getClass())) {
130             return false;
131         }
132         // For the complex below types let's skip the value range check for now
133         if (this.dataType == InetAddress.class) {
134             return true;
135         }
136         if (this.dataType() == Byte[].class) {
137             return true;
138         }
139         if (this.dataType() == NodeConnector.class) {
140             return true;
141         }
142
143         int val = 0;
144         int msk = 0;
145         if (value.getClass() == Integer.class || value.getClass() == int.class) {
146             val = ((Integer) value).intValue();
147             msk = (mask != null) ? ((Integer) mask).intValue() : 0;
148
149         } else if (value.getClass() == Short.class || value.getClass() == short.class) {
150             val = ((Short) value).intValue() & 0xffff;
151             msk = (mask != null) ? ((Short) mask).intValue() & 0xffff : 0;
152
153         } else if (value.getClass() == Byte.class || value.getClass() == byte.class) {
154             val = ((Byte) value).intValue() & 0xff;
155             msk = (mask != null) ? ((Byte) mask).intValue() & 0xff : 0;
156         }
157         return ((val >= minValue && val <= maxValue) && (mask == null || (msk >= minValue && msk <= maxValue)));
158
159     }
160
161     /**
162      * Return the mask value in 64 bits bitmask form
163      *
164      * @param mask
165      * @return
166      */
167     public long getBitMask(Object mask) {
168         if (this.dataType == InetAddress.class) {
169             // TODO handle Inet v4 and v6 v6 will have a second upper mask
170             return 0;
171         }
172         if (this.dataType() == Byte[].class) {
173             if (mask == null) {
174                 return 0xffffffffffffL;
175             }
176             byte mac[] = (byte[]) mask;
177             long bitmask = 0;
178             for (short i = 0; i < 6; i++) {
179                 bitmask |= ((mac[i] & 0xffL) << ((5 - i) * 8));
180             }
181             return bitmask;
182         }
183         if (this.dataType == Integer.class || this.dataType == int.class) {
184             return (mask == null) ? this.maxValue : ((Integer) mask).longValue();
185
186         }
187         if (this.dataType == Short.class || this.dataType == short.class) {
188             return (mask == null) ? this.maxValue : ((Short) mask).longValue();
189         }
190         if (this.dataType == Byte.class || this.dataType == byte.class) {
191             return (mask == null) ? this.maxValue : ((Byte) mask).longValue();
192
193         }
194         return 0L;
195     }
196
197     public String stringify(Object value) {
198         if (value == null) {
199             return null;
200         }
201
202         switch (this) {
203         case DL_DST:
204         case DL_SRC:
205             return HexEncode.bytesToHexStringFormat((byte[]) value);
206         case DL_TYPE:
207         case DL_VLAN:
208             return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString();
209         case NW_SRC:
210         case NW_DST:
211             return ((InetAddress) value).getHostAddress();
212         case NW_TOS:
213             return ((Integer) NetUtils.getUnsignedByte((Byte) value)).toString();
214         case TP_SRC:
215         case TP_DST:
216             return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString();
217         default:
218             break;
219         }
220         return value.toString();
221     }
222
223     public int valueHashCode(Object o) {
224         if (o == null) {
225             return 0;
226         }
227         switch (this) {
228         case DL_SRC:
229         case DL_DST:
230             return NetUtils.byteArray4ToInt((byte[])o);
231         default:
232             return o.hashCode();
233         }
234     }
235
236     public int hashCode(Object v, Object m) {
237         final int prime = 31;
238         int result = 1;
239         result = prime * result + this.calculateConsistentHashCode();
240
241         switch (this) {
242         case DL_SRC:
243         case DL_DST:
244             result = prime * result + ((v == null)? 0 : NetUtils.byteArray4ToInt((byte[])v));
245             result = prime * result + ((m == null)? 0 : NetUtils.byteArray4ToInt((byte[])m));
246             break;
247         case NW_SRC:
248         case NW_DST:
249             // Hash code has to take into account only prefix address
250             InetAddress ip = (InetAddress) v;
251             int maskLen = (m == null) ? ((ip instanceof Inet4Address) ? 32 : 128) : NetUtils
252                     .getSubnetMaskLength((InetAddress) m);
253             InetAddress prefix = NetUtils.getSubnetPrefix(ip, maskLen);
254             result = prime * result + ((v == null)? 0 : prefix.hashCode());
255             break;
256         default:
257             result = prime * result + ((v == null)? 0 : v.hashCode());
258             result = prime * result + ((m == null)? 0 : m.hashCode());
259         }
260         return result;
261     }
262     public boolean equalValues(Object a, Object b) {
263         if (a == b) {
264             return true;
265         }
266         if (a == null || b == null) {
267             return false;
268         }
269         switch (this) {
270         case DL_DST:
271         case DL_SRC:
272             return Arrays.equals((byte[]) a, (byte[]) b);
273         default:
274             return a.equals(b);
275         }
276     }
277
278     public boolean equalMasks(Object a, Object b) {
279         if (a == b) {
280             return true;
281         }
282         switch (this) {
283         case NW_SRC:
284         case NW_DST:
285             /*
286              * For network address mask, network node may return full mask for
287              * flows the controller generated with a null mask object
288              */
289             if (a == null || b == null) {
290                 InetAddress mask = (a == null) ? (InetAddress) b : (InetAddress) a;
291                 int maxLength = (mask instanceof Inet4Address) ? 32 : 128;
292                 return (NetUtils.getSubnetMaskLength(mask) == maxLength);
293             }
294         default:
295             if (a == null) {
296                 return false;
297             }
298             return a.equals(b);
299         }
300     }
301
302     public boolean equals(Object value1, Object value2, Object mask1, Object mask2) {
303         switch (this) {
304         case NW_SRC:
305         case NW_DST:
306             // Equality to be checked against prefix addresses
307             InetAddress thisIP = (InetAddress) value1;
308             int thisMaskLen = (mask1 == null) ? ((thisIP instanceof Inet4Address) ? 32 : 128) : NetUtils
309                     .getSubnetMaskLength((InetAddress) mask1);
310             InetAddress otherIP = (InetAddress) value2;
311             int otherMaskLen = (mask2 == null) ? ((otherIP instanceof Inet4Address) ? 32 : 128) : NetUtils
312                     .getSubnetMaskLength((InetAddress) mask2);
313
314             return NetUtils.getSubnetPrefix(thisIP, thisMaskLen)
315                     .equals(NetUtils.getSubnetPrefix(otherIP, otherMaskLen));
316         default:
317             return (this.equalValues(value1, value2) && this.equalMasks(mask1, mask2));
318         }
319     }
320
321     public int calculateConsistentHashCode() {
322         if (this.id != null) {
323             return this.id.hashCode();
324         } else {
325             return 0;
326         }
327     }
328 }