blob: aaa31ebecf1989917fdf3d711b99401e7e74cda7 [file] [log] [blame]
Yotam Harcholf3f11152013-09-05 16:47:16 -07001package org.projectfloodlight.openflow.types;
2
3import org.jboss.netty.buffer.ChannelBuffer;
4import org.projectfloodlight.openflow.exceptions.OFParseError;
5import org.projectfloodlight.openflow.util.HexString;
6
Andreas Wundsam22ba3af2013-10-04 16:00:30 -07007import com.google.common.hash.PrimitiveSink;
Andreas Wundsam85c961f2013-09-29 21:22:12 -07008import com.google.common.primitives.Longs;
9
Yotam Harcholf3f11152013-09-05 16:47:16 -070010/**
11 * Wrapper around a 6 byte mac address.
12 *
13 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
14 */
15
16public class MacAddress implements OFValueType<MacAddress> {
17 static final int MacAddrLen = 6;
18 private final long rawValue;
19
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070020 private final static long NONE_VAL = 0x0L;
21 public static final MacAddress NONE = new MacAddress(NONE_VAL);
22
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070023 private final static long BROADCAST_VAL = 0x0000FFFFFFFFFFFFL;
24 public static final MacAddress BROADCAST = new MacAddress(BROADCAST_VAL);
25
Yotam Harcholf3f11152013-09-05 16:47:16 -070026 public static final MacAddress NO_MASK = MacAddress.of(0xFFFFFFFFFFFFFFFFl);
27 public static final MacAddress FULL_MASK = MacAddress.of(0x0);
28
29 private MacAddress(final long rawValue) {
30 this.rawValue = rawValue;
31 }
32
33 public static MacAddress of(final byte[] address) {
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070034 if (address.length != MacAddrLen)
35 throw new IllegalArgumentException(
36 "Mac address byte array must be exactly 6 bytes long; length = " + address.length);
Yotam Harcholf3f11152013-09-05 16:47:16 -070037 long raw =
38 (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32
39 | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16
40 | (address[4] & 0xFFL) << 8 | (address[5] & 0xFFL);
41 return MacAddress.of(raw);
42 }
43
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070044 public static MacAddress of(long raw) {
45 raw &= BROADCAST_VAL;
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070046 if(raw == NONE_VAL)
47 return NONE;
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070048 if (raw == BROADCAST_VAL)
49 return BROADCAST;
Yotam Harcholf3f11152013-09-05 16:47:16 -070050 return new MacAddress(raw);
51 }
52
53 public static MacAddress of(final String string) {
54 int index = 0;
55 int shift = 40;
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070056 final String FORMAT_ERROR = "Mac address is not well-formed. " +
57 "It must consist of 6 hex digit pairs separated by colons: ";
Yotam Harcholf3f11152013-09-05 16:47:16 -070058
59 long raw = 0;
60 if (string.length() != 6 * 2 + 5)
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070061 throw new IllegalArgumentException(FORMAT_ERROR + string);
Yotam Harcholf3f11152013-09-05 16:47:16 -070062
63 while (shift >= 0) {
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070064 int digit1 = Character.digit(string.charAt(index++), 16);
65 int digit2 = Character.digit(string.charAt(index++), 16);
66 if ((digit1 < 0) || (digit2 < 0))
67 throw new IllegalArgumentException(FORMAT_ERROR + string);
68 raw |= ((long) (digit1 << 4 | digit2)) << shift;
Yotam Harcholf3f11152013-09-05 16:47:16 -070069
70 if (shift == 0)
71 break;
72 if (string.charAt(index++) != ':')
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070073 throw new IllegalArgumentException(FORMAT_ERROR + string);
Yotam Harcholf3f11152013-09-05 16:47:16 -070074 shift -= 8;
75 }
76 return MacAddress.of(raw);
77 }
78
79 volatile byte[] bytesCache = null;
80
81 public byte[] getBytes() {
82 if (bytesCache == null) {
83 synchronized (this) {
84 if (bytesCache == null) {
85 bytesCache =
86 new byte[] { (byte) ((rawValue >> 40) & 0xFF),
87 (byte) ((rawValue >> 32) & 0xFF),
88 (byte) ((rawValue >> 24) & 0xFF),
89 (byte) ((rawValue >> 16) & 0xFF),
90 (byte) ((rawValue >> 8) & 0xFF),
91 (byte) ((rawValue >> 0) & 0xFF) };
92 }
93 }
94 }
95 return bytesCache;
96 }
97
Rob Vaterlaus83f40ab2013-10-14 15:44:46 -070098 /**
99 * Returns {@code true} if the MAC address is the broadcast address.
100 * @return {@code true} if the MAC address is the broadcast address.
101 */
102 public boolean isBroadcast() {
103 return this == BROADCAST;
104 }
105
106 /**
107 * Returns {@code true} if the MAC address is a multicast address.
108 * @return {@code true} if the MAC address is a multicast address.
109 */
110 public boolean isMulticast() {
111 if (isBroadcast()) {
112 return false;
113 }
114 return (rawValue & (0x01L << 40)) != 0;
115 }
116
Yotam Harcholf3f11152013-09-05 16:47:16 -0700117 @Override
118 public int getLength() {
119 return MacAddrLen;
120 }
121
122 @Override
123 public String toString() {
124 return HexString.toHexString(rawValue, 6);
125 }
126
127 @Override
128 public int hashCode() {
129 final int prime = 31;
130 int result = 1;
131 result = prime * result + (int) (rawValue ^ (rawValue >>> 32));
132 return result;
133 }
134
135 @Override
136 public boolean equals(final Object obj) {
137 if (this == obj)
138 return true;
139 if (obj == null)
140 return false;
141 if (getClass() != obj.getClass())
142 return false;
143 MacAddress other = (MacAddress) obj;
144 if (rawValue != other.rawValue)
145 return false;
146 return true;
147 }
148
149 public long getLong() {
150 return rawValue;
151 }
152
153 public void write6Bytes(ChannelBuffer c) {
154 c.writeInt((int) (this.rawValue >> 16));
155 c.writeShort((int) this.rawValue & 0xFFFF);
156 }
157
158 public static MacAddress read6Bytes(ChannelBuffer c) throws OFParseError {
159 long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort();
160 return MacAddress.of(raw);
161 }
162
163 @Override
164 public MacAddress applyMask(MacAddress mask) {
165 return MacAddress.of(this.rawValue & mask.rawValue);
166 }
167
Andreas Wundsam85c961f2013-09-29 21:22:12 -0700168 @Override
169 public int compareTo(MacAddress o) {
170 return Longs.compare(rawValue, o.rawValue);
171 }
172
Andreas Wundsam22ba3af2013-10-04 16:00:30 -0700173 @Override
174 public void putTo(PrimitiveSink sink) {
175 sink.putInt((int) (this.rawValue >> 16));
176 sink.putShort((short) (this.rawValue & 0xFFFF));
177 }
178
Yotam Harcholf3f11152013-09-05 16:47:16 -0700179
180
181}