Initial opendaylight infrastructure commit!!
[controller.git] / opendaylight / sal / api / src / main / java / org / opendaylight / controller / sal / match / MatchType.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.sal.match;
11
12 import java.net.InetAddress;
13
14 import org.opendaylight.controller.sal.core.NodeConnector;
15
16 /**
17  * Represents the binding between the id, the value and mask type and the range values
18  * of the elements type that can be matched on the network frame/packet/message
19  *
20  *
21  *
22  */
23 public enum MatchType {
24     IN_PORT("inPort", 1 << 0, NodeConnector.class, 1, 0), DL_SRC("dlSrc",
25             1 << 1, Byte[].class, 0, 0xffffffffffffL), DL_DST("dlDst", 1 << 2,
26             Byte[].class, 0, 0xffffffffffffL), DL_VLAN("dlVlan", 1 << 3,
27             Short.class, 2, 0xfff), // 2 bytes
28     DL_VLAN_PR("dlVlanPriority", 1 << 4, Byte.class, 0, 0x7), // 3 bits
29     DL_OUTER_VLAN("dlOuterVlan", 1 << 5, Short.class, 2, 0xfff), DL_OUTER_VLAN_PR(
30             "dlOuterVlanPriority", 1 << 6, Short.class, 0, 0x7), DL_TYPE(
31             "dlType", 1 << 7, Short.class, 0, 0xffff), // 2 bytes
32     NW_TOS("nwTOS", 1 << 8, Byte.class, 0, 0xff), // 1 byte
33     NW_PROTO("nwProto", 1 << 9, Byte.class, 0, 0xff), // 1 byte
34     NW_SRC("nwSrc", 1 << 10, InetAddress.class, 0, 0), NW_DST("nwDst", 1 << 11,
35             InetAddress.class, 0, 0), TP_SRC("tpSrc", 1 << 12, Short.class, 1,
36             0xffff), // 2 bytes
37     TP_DST("tpDst", 1 << 13, Short.class, 1, 0xffff); // 2 bytes
38
39     private String id;
40     private int index;
41     private Class<?> dataType;
42     private long minValue;
43     private long maxValue;
44
45     private MatchType(String id, int index, Class<?> dataType, long minValue,
46             long maxValue) {
47         this.id = id;
48         this.index = index;
49         this.dataType = dataType;
50         this.minValue = minValue;
51         this.maxValue = maxValue;
52     }
53
54     public String id() {
55         return id;
56     }
57
58     public int getIndex() {
59         return index;
60     }
61
62     public Class<?> dataType() {
63         return dataType;
64     }
65
66     public String getRange() {
67         return "[0x" + Long.toHexString(minValue) + "-0x"
68                 + Long.toHexString(maxValue) + "]";
69     }
70
71     /**
72      *  Perform the assignment type validation
73      * @param value
74      * @param mask
75      * @return
76      */
77     public boolean isCongruentType(Object value, Object mask) {
78         // Mask type has to match value type
79         if (mask != null && (mask.getClass() != value.getClass())) {
80             return false;
81         }
82
83         Class<?> e = this.dataType();
84         Class<?> g = value.getClass();
85
86         // This is all what we need, if value type is same of match required type
87         if (g.equals(e)) {
88             return true;
89         }
90
91         // This is for the numeric class vs primitive congruence
92         // For what concerns here, for instance, Integer is congruent to int
93         if (e == Short.class) {
94             return g.equals(short.class);
95         }
96
97         if (e == Integer.class) {
98             return g.equals(int.class);
99         }
100
101         if (e == Byte.class) {
102             return g.equals(byte.class);
103         }
104
105         if (e == Byte[].class) {
106             return g.equals(byte[].class);
107         }
108
109         if (e == InetAddress.class) {
110             return g.getSuperclass().equals(InetAddress.class);
111         }
112         return false;
113     }
114
115     /**
116      * Perform the value and mask range validation
117      * @param value
118      * @param mask
119      * @return
120      */
121     public boolean isValid(Object value, Object mask) {
122         // Skip if main error
123         if (mask != null && (mask.getClass() != value.getClass())) {
124             return false;
125         }
126         // For the complex below types let's skip the value range check for now
127         if (this.dataType == InetAddress.class) {
128             return true;
129         }
130         if (this.dataType() == Byte[].class) {
131             return true;
132         }
133         if (this.dataType() == NodeConnector.class) {
134             return true;
135         }
136
137         int val = 0;
138         int msk = 0;
139         if (value.getClass() == Integer.class || value.getClass() == int.class) {
140             val = ((Integer) value).intValue();
141             msk = (mask != null) ? ((Integer) mask).intValue() : 0;
142
143         } else if (value.getClass() == Short.class
144                 || value.getClass() == short.class) {
145             val = ((Short) value).intValue() & 0xffff;
146             msk = (mask != null) ? ((Short) mask).intValue() & 0xffff : 0;
147
148         } else if (value.getClass() == Byte.class
149                 || value.getClass() == byte.class) {
150             val = ((Byte) value).intValue() & 0xff;
151             msk = (mask != null) ? ((Byte) mask).intValue() & 0xff : 0;
152         }
153         return ((val >= minValue && val <= maxValue) && (mask == null || (msk >= minValue && msk <= maxValue)));
154
155     }
156
157     /**
158      * Return the mask value in 64 bits bitmask form
159      * @param mask
160      * @return
161      */
162     public long getBitMask(Object mask) {
163         if (this.dataType == InetAddress.class) {
164             //TODO handle Inet v4 and v6 v6 will have a second upper mask
165             return 0;
166         }
167         if (this.dataType() == Byte[].class) {
168             if (mask == null) {
169                 return 0xffffffffffffL;
170             }
171             byte mac[] = (byte[]) mask;
172             long bitmask = 0;
173             for (short i = 0; i < 6; i++) {
174                 //                              bitmask |= (((long)mac[i] & 0xffL) << (long)((5-i)*8));
175                 bitmask |= (((long) mac[i] & 0xffL) << ((5 - i) * 8));
176             }
177             return bitmask;
178         }
179         if (this.dataType == Integer.class || this.dataType == int.class) {
180             return (mask == null) ? this.maxValue : ((Integer) mask)
181                     .longValue();
182
183         }
184         if (this.dataType == Short.class || this.dataType == short.class) {
185             return (mask == null) ? this.maxValue : ((Short) mask).longValue();
186         }
187         if (this.dataType == Byte.class || this.dataType == byte.class) {
188             return (mask == null) ? this.maxValue : ((Byte) mask).longValue();
189
190         }
191         return 0L;
192     }
193 }