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