ISSUE:
[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 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 values
20  * of the elements type that can be matched on the network frame/packet/message
21  *
22  *
23  *
24  */
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, 1, 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, 1, 0xffff), // 2 bytes
39     TP_DST("tpDst", 1 << 13, Short.class, 1, 0xffff); // 2 bytes
40
41     private String id;
42     private int index;
43     private Class<?> dataType;
44     private long minValue;
45     private long maxValue;
46
47     private MatchType(String id, int index, Class<?> dataType, long minValue,
48             long maxValue) {
49         this.id = id;
50         this.index = index;
51         this.dataType = dataType;
52         this.minValue = minValue;
53         this.maxValue = maxValue;
54     }
55
56     public String id() {
57         return id;
58     }
59
60     public int getIndex() {
61         return index;
62     }
63
64     public Class<?> dataType() {
65         return dataType;
66     }
67
68     public String getRange() {
69         return "[0x" + Long.toHexString(minValue) + "-0x"
70                 + Long.toHexString(maxValue) + "]";
71     }
72
73     /**
74      *  Perform the assignment type validation
75      * @param value
76      * @param mask
77      * @return
78      */
79     public boolean isCongruentType(Object value, Object mask) {
80         // Mask type has to match value type
81         if (mask != null && (mask.getClass() != value.getClass())) {
82             return false;
83         }
84
85         Class<?> e = this.dataType();
86         Class<?> g = value.getClass();
87
88         // This is all what we need, if value type is same of match required type
89         if (g.equals(e)) {
90             return true;
91         }
92
93         // This is for the numeric class vs primitive congruence
94         // For what concerns here, for instance, Integer is congruent to int
95         if (e == Short.class) {
96             return g.equals(short.class);
97         }
98
99         if (e == Integer.class) {
100             return g.equals(int.class);
101         }
102
103         if (e == Byte.class) {
104             return g.equals(byte.class);
105         }
106
107         if (e == Byte[].class) {
108             return g.equals(byte[].class);
109         }
110
111         if (e == InetAddress.class) {
112             return g.getSuperclass().equals(InetAddress.class);
113         }
114         return false;
115     }
116
117     /**
118      * Perform the value and mask range validation
119      * @param value
120      * @param mask
121      * @return
122      */
123     public boolean isValid(Object value, Object mask) {
124         // Skip if main error
125         if (mask != null && (mask.getClass() != value.getClass())) {
126             return false;
127         }
128         // For the complex below types let's skip the value range check for now
129         if (this.dataType == InetAddress.class) {
130             return true;
131         }
132         if (this.dataType() == Byte[].class) {
133             return true;
134         }
135         if (this.dataType() == NodeConnector.class) {
136             return true;
137         }
138
139         int val = 0;
140         int msk = 0;
141         if (value.getClass() == Integer.class || value.getClass() == int.class) {
142             val = ((Integer) value).intValue();
143             msk = (mask != null) ? ((Integer) mask).intValue() : 0;
144
145         } else if (value.getClass() == Short.class
146                 || value.getClass() == short.class) {
147             val = ((Short) value).intValue() & 0xffff;
148             msk = (mask != null) ? ((Short) mask).intValue() & 0xffff : 0;
149
150         } else if (value.getClass() == Byte.class
151                 || value.getClass() == byte.class) {
152             val = ((Byte) value).intValue() & 0xff;
153             msk = (mask != null) ? ((Byte) mask).intValue() & 0xff : 0;
154         }
155         return ((val >= minValue && val <= maxValue) && (mask == null || (msk >= minValue && msk <= maxValue)));
156
157     }
158
159     /**
160      * Return the mask value in 64 bits bitmask form
161      * @param mask
162      * @return
163      */
164     public long getBitMask(Object mask) {
165         if (this.dataType == InetAddress.class) {
166             //TODO handle Inet v4 and v6 v6 will have a second upper mask
167             return 0;
168         }
169         if (this.dataType() == Byte[].class) {
170             if (mask == null) {
171                 return 0xffffffffffffL;
172             }
173             byte mac[] = (byte[]) mask;
174             long bitmask = 0;
175             for (short i = 0; i < 6; i++) {
176                 //                              bitmask |= (((long)mac[i] & 0xffL) << (long)((5-i)*8));
177                 bitmask |= (((long) mac[i] & 0xffL) << ((5 - i) * 8));
178             }
179             return bitmask;
180         }
181         if (this.dataType == Integer.class || this.dataType == int.class) {
182             return (mask == null) ? this.maxValue : ((Integer) mask)
183                     .longValue();
184
185         }
186         if (this.dataType == Short.class || this.dataType == short.class) {
187             return (mask == null) ? this.maxValue : ((Short) mask).longValue();
188         }
189         if (this.dataType == Byte.class || this.dataType == byte.class) {
190             return (mask == null) ? this.maxValue : ((Byte) mask).longValue();
191
192         }
193         return 0L;
194     }
195
196         public String stringify(Object value) {
197                 if (value == null) {
198                         return null;
199                 }
200                 
201                 switch (this) {
202                 case DL_DST:
203                 case DL_SRC:
204                         return HexEncode.bytesToHexStringFormat((byte[])value);
205                 case DL_TYPE:
206                 case DL_VLAN:
207                         return ((Integer) NetUtils.getUnsignedShort((Short)value))
208                                         .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))
214                                         .toString();
215                 case TP_SRC:
216                 case TP_DST:
217                         return ((Integer) NetUtils.getUnsignedShort((Short)value))
218                                         .toString();
219                 default:
220                         break;
221                 }
222                 return value.toString();
223         }
224 }