2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.sal.match;
11 import java.net.Inet4Address;
12 import java.net.InetAddress;
13 import java.util.Arrays;
15 import org.opendaylight.controller.sal.core.NodeConnector;
16 import org.opendaylight.controller.sal.utils.HexEncode;
17 import org.opendaylight.controller.sal.utils.NetUtils;
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
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, 0, 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, 0x3f), // 6 bits (DSCP field)
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, 0, 0xffff), // 2 bytes
38 TP_DST("tpDst", 1 << 13, Short.class, 0, 0xffff); // 2 bytes
40 // Used to indicate that no VLAN ID is set.
41 public static final short DL_VLAN_NONE = (short) 0;
45 private Class<?> dataType;
46 private long minValue;
47 private long maxValue;
49 private MatchType(String id, int index, Class<?> dataType, long minValue, long maxValue) {
52 this.dataType = dataType;
53 this.minValue = minValue;
54 this.maxValue = maxValue;
61 public int getIndex() {
65 public Class<?> dataType() {
69 public String getRange() {
70 return "[0x" + Long.toHexString(minValue) + "-0x" + Long.toHexString(maxValue) + "]";
74 * Perform the assignment type validation
80 public boolean isCongruentType(Object value, Object mask) {
81 // Mask type has to match value type
82 if (mask != null && (mask.getClass() != value.getClass())) {
86 Class<?> e = this.dataType();
87 Class<?> g = value.getClass();
89 // This is all what we need, if value type is same of match required
95 // This is for the numeric class vs primitive congruence
96 // For what concerns here, for instance, Integer is congruent to int
97 if (e == Short.class) {
98 return g.equals(short.class);
101 if (e == Integer.class) {
102 return g.equals(int.class);
105 if (e == Byte.class) {
106 return g.equals(byte.class);
109 if (e == Byte[].class) {
110 return g.equals(byte[].class);
113 if (e == InetAddress.class) {
114 return g.getSuperclass().equals(InetAddress.class);
120 * Perform the value and mask range validation
126 public boolean isValid(Object value, Object mask) {
127 // Skip if main error
128 if (mask != null && (mask.getClass() != value.getClass())) {
131 // For the complex below types let's skip the value range check for now
132 if (this.dataType == InetAddress.class) {
135 if (this.dataType() == Byte[].class) {
138 if (this.dataType() == NodeConnector.class) {
144 if (value.getClass() == Integer.class || value.getClass() == int.class) {
145 val = ((Integer) value).intValue();
146 msk = (mask != null) ? ((Integer) mask).intValue() : 0;
148 } else if (value.getClass() == Short.class || value.getClass() == short.class) {
149 val = ((Short) value).intValue() & 0xffff;
150 msk = (mask != null) ? ((Short) mask).intValue() & 0xffff : 0;
152 } else if (value.getClass() == Byte.class || value.getClass() == byte.class) {
153 val = ((Byte) value).intValue() & 0xff;
154 msk = (mask != null) ? ((Byte) mask).intValue() & 0xff : 0;
156 return ((val >= minValue && val <= maxValue) && (mask == null || (msk >= minValue && msk <= maxValue)));
161 * Return the mask value in 64 bits bitmask form
166 public long getBitMask(Object mask) {
167 if (this.dataType == InetAddress.class) {
168 // TODO handle Inet v4 and v6 v6 will have a second upper mask
171 if (this.dataType() == Byte[].class) {
173 return 0xffffffffffffL;
175 byte mac[] = (byte[]) mask;
177 for (short i = 0; i < 6; i++) {
178 bitmask |= ((mac[i] & 0xffL) << ((5 - i) * 8));
182 if (this.dataType == Integer.class || this.dataType == int.class) {
183 return (mask == null) ? this.maxValue : ((Integer) mask).longValue();
186 if (this.dataType == Short.class || this.dataType == short.class) {
187 return (mask == null) ? this.maxValue : ((Short) mask).longValue();
189 if (this.dataType == Byte.class || this.dataType == byte.class) {
190 return (mask == null) ? this.maxValue : ((Byte) mask).longValue();
196 public String stringify(Object value) {
204 return HexEncode.bytesToHexStringFormat((byte[]) value);
207 return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString();
210 return ((InetAddress) value).getHostAddress();
212 return ((Integer) NetUtils.getUnsignedByte((Byte) value)).toString();
215 return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString();
219 return value.toString();
222 public int valueHashCode(Object o) {
229 return NetUtils.byteArray4ToInt((byte[])o);
235 public int hashCode(Object v, Object m) {
236 final int prime = 31;
238 result = prime * result + this.calculateConsistentHashCode();
243 result = prime * result + ((v == null)? 0 : NetUtils.byteArray4ToInt((byte[])v));
244 result = prime * result + ((m == null)? 0 : NetUtils.byteArray4ToInt((byte[])m));
248 // Hash code has to take into account only prefix address
249 InetAddress ip = (InetAddress) v;
250 int maskLen = (m == null) ? ((ip instanceof Inet4Address) ? 32 : 128) : NetUtils
251 .getSubnetMaskLength((InetAddress) m);
252 InetAddress prefix = NetUtils.getSubnetPrefix(ip, maskLen);
253 result = prime * result + ((v == null)? 0 : prefix.hashCode());
256 result = prime * result + ((v == null)? 0 : v.hashCode());
257 result = prime * result + ((m == null)? 0 : m.hashCode());
261 public boolean equalValues(Object a, Object b) {
265 if (a == null || b == null) {
271 return Arrays.equals((byte[]) a, (byte[]) b);
277 public boolean equalMasks(Object a, Object b) {
285 * For network address mask, network node may return full mask for
286 * flows the controller generated with a null mask object
288 if (a == null || b == null) {
289 InetAddress mask = (a == null) ? (InetAddress) b : (InetAddress) a;
290 int maxLength = (mask instanceof Inet4Address) ? 32 : 128;
291 return (NetUtils.getSubnetMaskLength(mask) == maxLength);
301 public boolean equals(Object value1, Object value2, Object mask1, Object mask2) {
305 // Equality to be checked against prefix addresses
306 InetAddress thisIP = (InetAddress) value1;
307 int thisMaskLen = (mask1 == null) ? ((thisIP instanceof Inet4Address) ? 32 : 128) : NetUtils
308 .getSubnetMaskLength((InetAddress) mask1);
309 InetAddress otherIP = (InetAddress) value2;
310 int otherMaskLen = (mask2 == null) ? ((otherIP instanceof Inet4Address) ? 32 : 128) : NetUtils
311 .getSubnetMaskLength((InetAddress) mask2);
313 return NetUtils.getSubnetPrefix(thisIP, thisMaskLen)
314 .equals(NetUtils.getSubnetPrefix(otherIP, otherMaskLen));
316 return (this.equalValues(value1, value2) && this.equalMasks(mask1, mask2));
320 public int calculateConsistentHashCode() {
321 if (this.id != null) {
322 return this.id.hashCode();