Checkstyle enforcer
[controller.git] / opendaylight / 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.InetAddress;
12 import java.util.Arrays;
13
14 import org.opendaylight.controller.sal.core.NodeConnector;
15 import org.opendaylight.controller.sal.utils.HexEncode;
16 import org.opendaylight.controller.sal.utils.NetUtils;
17
18 /**
19  * Represents the binding between the id, the value and mask type and the range
20  * values of the elements type that can be matched on the network
21  * frame/packet/message
22  *
23  *
24  *
25  */
26 public enum MatchType {
27     IN_PORT("inPort", 1 << 0, NodeConnector.class, 1, 0),
28     DL_SRC("dlSrc", 1 << 1, Byte[].class, 0, 0xffffffffffffL),
29     DL_DST("dlDst", 1 << 2, Byte[].class, 0, 0xffffffffffffL),
30     DL_VLAN("dlVlan", 1 << 3, Short.class, 1, 0xfff), // 2 bytes
31     DL_VLAN_PR("dlVlanPriority", 1 << 4, Byte.class, 0, 0x7), // 3 bits
32     DL_OUTER_VLAN("dlOuterVlan", 1 << 5, Short.class, 1, 0xfff),
33     DL_OUTER_VLAN_PR("dlOuterVlanPriority", 1 << 6, Short.class, 0, 0x7),
34     DL_TYPE("dlType", 1 << 7, Short.class, 0, 0xffff), // 2 bytes
35     NW_TOS("nwTOS", 1 << 8, Byte.class, 0, 0x3f), // 6 bits (DSCP field)
36     NW_PROTO("nwProto", 1 << 9, Byte.class, 0, 0xff), // 1 byte
37     NW_SRC("nwSrc", 1 << 10, InetAddress.class, 0, 0),
38     NW_DST("nwDst", 1 << 11, InetAddress.class, 0, 0),
39     TP_SRC("tpSrc", 1 << 12, Short.class, 1, 0xffff), // 2 bytes
40     TP_DST("tpDst", 1 << 13, Short.class, 1, 0xffff); // 2 bytes
41
42     private String id;
43     private int index;
44     private Class<?> dataType;
45     private long minValue;
46     private long maxValue;
47
48     private MatchType(String id, int index, Class<?> dataType, long minValue,
49             long maxValue) {
50         this.id = id;
51         this.index = index;
52         this.dataType = dataType;
53         this.minValue = minValue;
54         this.maxValue = maxValue;
55     }
56
57     public String id() {
58         return id;
59     }
60
61     public int getIndex() {
62         return index;
63     }
64
65     public Class<?> dataType() {
66         return dataType;
67     }
68
69     public String getRange() {
70         return "[0x" + Long.toHexString(minValue) + "-0x"
71                 + 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
150                 || value.getClass() == short.class) {
151             val = ((Short) value).intValue() & 0xffff;
152             msk = (mask != null) ? ((Short) mask).intValue() & 0xffff : 0;
153
154         } else if (value.getClass() == Byte.class
155                 || value.getClass() == byte.class) {
156             val = ((Byte) value).intValue() & 0xff;
157             msk = (mask != null) ? ((Byte) mask).intValue() & 0xff : 0;
158         }
159         return ((val >= minValue && val <= maxValue) && (mask == null || (msk >= minValue && msk <= maxValue)));
160
161     }
162
163     /**
164      * Return the mask value in 64 bits bitmask form
165      *
166      * @param mask
167      * @return
168      */
169     public long getBitMask(Object mask) {
170         if (this.dataType == InetAddress.class) {
171             // TODO handle Inet v4 and v6 v6 will have a second upper mask
172             return 0;
173         }
174         if (this.dataType() == Byte[].class) {
175             if (mask == null) {
176                 return 0xffffffffffffL;
177             }
178             byte mac[] = (byte[]) mask;
179             long bitmask = 0;
180             for (short i = 0; i < 6; i++) {
181                 bitmask |= (((long) mac[i] & 0xffL) << ((5 - i) * 8));
182             }
183             return bitmask;
184         }
185         if (this.dataType == Integer.class || this.dataType == int.class) {
186             return (mask == null) ? this.maxValue : ((Integer) mask)
187                     .longValue();
188
189         }
190         if (this.dataType == Short.class || this.dataType == short.class) {
191             return (mask == null) ? this.maxValue : ((Short) mask).longValue();
192         }
193         if (this.dataType == Byte.class || this.dataType == byte.class) {
194             return (mask == null) ? this.maxValue : ((Byte) mask).longValue();
195
196         }
197         return 0L;
198     }
199
200     public String stringify(Object value) {
201         if (value == null) {
202             return null;
203         }
204
205         switch (this) {
206         case DL_DST:
207         case DL_SRC:
208             return HexEncode.bytesToHexStringFormat((byte[]) value);
209         case DL_TYPE:
210         case DL_VLAN:
211             return ((Integer) NetUtils.getUnsignedShort((Short) value))
212                     .toString();
213         case NW_SRC:
214         case NW_DST:
215             return ((InetAddress) value).getHostAddress();
216         case NW_TOS:
217             return ((Integer) NetUtils.getUnsignedByte((Byte) value))
218                     .toString();
219         case TP_SRC:
220         case TP_DST:
221             return ((Integer) NetUtils.getUnsignedShort((Short) value))
222                     .toString();
223         default:
224             break;
225         }
226         return value.toString();
227     }
228
229     public boolean equalValues(Object a, Object b) {
230         if (a == b) {
231             return true;
232         }
233         if (a == null || b == null) {
234             return false;
235         }
236         switch (this) {
237         case DL_DST:
238         case DL_SRC:
239             return Arrays.equals((byte[]) a, (byte[]) b);
240         default:
241             return a.equals(b);
242         }
243     }
244
245     public boolean equalMasks(Object a, Object b) {
246         if (a == b) {
247             return true;
248         }
249         switch (this) {
250         case NW_SRC:
251         case NW_DST:
252             /*
253              * For network address mask, network node may return full mask for
254              * flows the controller generated with a null mask object
255              */
256             byte maskBytes[] = null;
257             if (a == null) {
258                 maskBytes = ((InetAddress) b).getAddress();
259             } else if (b == null) {
260                 maskBytes = ((InetAddress) a).getAddress();
261             }
262             if (maskBytes != null) {
263                 return (NetUtils.getSubnetMaskLength(maskBytes) == 0);
264             }
265         default:
266             if (a == null) {
267                 return false;
268             }
269             return a.equals(b);
270         }
271     }
272 }