blob: 08aa6e3a08897f1a6348799e5448fd574000cf21 [file] [log] [blame]
alshabibc4901cd2014-09-05 16:50:40 -07001/*******************************************************************************
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************/
16package org.onlab.packet;
17
18import java.util.Arrays;
19
20/**
21 * The class representing MAC address.
22 *
alshabibc4901cd2014-09-05 16:50:40 -070023 */
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070024public class MacAddress {
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -070025
tom545708e2014-10-09 17:10:02 -070026 public static final MacAddress ZERO = valueOf("00:00:00:00:00:00");
27 public static final MacAddress BROADCAST = valueOf("ff:ff:ff:ff:ff:ff");
28
29 public static final byte[] ZERO_MAC_ADDRESS = ZERO.getAddress();
30 public static final byte[] BROADCAST_MAC = BROADCAST.getAddress();
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -070031
alshabibc4901cd2014-09-05 16:50:40 -070032 public static final int MAC_ADDRESS_LENGTH = 6;
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070033 private byte[] address = new byte[MacAddress.MAC_ADDRESS_LENGTH];
alshabibc4901cd2014-09-05 16:50:40 -070034
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070035 public MacAddress(final byte[] address) {
36 this.address = Arrays.copyOf(address, MacAddress.MAC_ADDRESS_LENGTH);
alshabibc4901cd2014-09-05 16:50:40 -070037 }
38
39 /**
40 * Returns a MAC address instance representing the value of the specified
41 * {@code String}.
42 *
43 * @param address
44 * the String representation of the MAC Address to be parsed.
45 * @return a MAC Address instance representing the value of the specified
46 * {@code String}.
47 * @throws IllegalArgumentException
48 * if the string cannot be parsed as a MAC address.
49 */
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070050 public static MacAddress valueOf(final String address) {
alshabibc4901cd2014-09-05 16:50:40 -070051 final String[] elements = address.split(":");
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070052 if (elements.length != MacAddress.MAC_ADDRESS_LENGTH) {
alshabibc4901cd2014-09-05 16:50:40 -070053 throw new IllegalArgumentException(
54 "Specified MAC Address must contain 12 hex digits"
55 + " separated pairwise by :'s.");
56 }
57
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070058 final byte[] addressInBytes = new byte[MacAddress.MAC_ADDRESS_LENGTH];
59 for (int i = 0; i < MacAddress.MAC_ADDRESS_LENGTH; i++) {
alshabibc4901cd2014-09-05 16:50:40 -070060 final String element = elements[i];
61 addressInBytes[i] = (byte) Integer.parseInt(element, 16);
62 }
63
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070064 return new MacAddress(addressInBytes);
alshabibc4901cd2014-09-05 16:50:40 -070065 }
66
67 /**
68 * Returns a MAC address instance representing the specified {@code byte}
69 * array.
70 *
71 * @param address
72 * the byte array to be parsed.
73 * @return a MAC address instance representing the specified {@code byte}
74 * array.
75 * @throws IllegalArgumentException
76 * if the byte array cannot be parsed as a MAC address.
77 */
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070078 public static MacAddress valueOf(final byte[] address) {
79 if (address.length != MacAddress.MAC_ADDRESS_LENGTH) {
alshabibc4901cd2014-09-05 16:50:40 -070080 throw new IllegalArgumentException("the length is not "
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070081 + MacAddress.MAC_ADDRESS_LENGTH);
alshabibc4901cd2014-09-05 16:50:40 -070082 }
83
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070084 return new MacAddress(address);
alshabibc4901cd2014-09-05 16:50:40 -070085 }
86
87 /**
88 * Returns a MAC address instance representing the specified {@code long}
89 * value. The lower 48 bits of the long value are used to parse as a MAC
90 * address.
91 *
92 * @param address
93 * the long value to be parsed. The lower 48 bits are used for a
94 * MAC address.
95 * @return a MAC address instance representing the specified {@code long}
96 * value.
97 * @throws IllegalArgumentException
98 * if the long value cannot be parsed as a MAC address.
99 */
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700100 public static MacAddress valueOf(final long address) {
alshabibc4901cd2014-09-05 16:50:40 -0700101 final byte[] addressInBytes = new byte[] {
102 (byte) (address >> 40 & 0xff), (byte) (address >> 32 & 0xff),
103 (byte) (address >> 24 & 0xff), (byte) (address >> 16 & 0xff),
104 (byte) (address >> 8 & 0xff), (byte) (address >> 0 & 0xff) };
105
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700106 return new MacAddress(addressInBytes);
alshabibc4901cd2014-09-05 16:50:40 -0700107 }
108
109 /**
110 * Returns the length of the {@code MACAddress}.
111 *
112 * @return the length of the {@code MACAddress}.
113 */
114 public int length() {
115 return this.address.length;
116 }
117
118 /**
119 * Returns the value of the {@code MACAddress} as a {@code byte} array.
120 *
121 * @return the numeric value represented by this object after conversion to
122 * type {@code byte} array.
123 */
124 public byte[] toBytes() {
125 return Arrays.copyOf(this.address, this.address.length);
126 }
127
128 /**
129 * Returns the value of the {@code MACAddress} as a {@code long}.
130 *
131 * @return the numeric value represented by this object after conversion to
132 * type {@code long}.
133 */
134 public long toLong() {
135 long mac = 0;
136 for (int i = 0; i < 6; i++) {
137 final long t = (this.address[i] & 0xffL) << (5 - i) * 8;
138 mac |= t;
139 }
140 return mac;
141 }
142
143 /**
144 * Returns {@code true} if the MAC address is the broadcast address.
145 *
146 * @return {@code true} if the MAC address is the broadcast address.
147 */
148 public boolean isBroadcast() {
149 for (final byte b : this.address) {
150 if (b != -1) {
151 return false;
152 }
153 }
154 return true;
155 }
156
157 /**
158 * Returns {@code true} if the MAC address is the multicast address.
159 *
160 * @return {@code true} if the MAC address is the multicast address.
161 */
162 public boolean isMulticast() {
163 if (this.isBroadcast()) {
164 return false;
165 }
166 return (this.address[0] & 0x01) != 0;
167 }
168
169 @Override
170 public boolean equals(final Object o) {
171 if (o == this) {
172 return true;
173 }
174
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700175 if (!(o instanceof MacAddress)) {
alshabibc4901cd2014-09-05 16:50:40 -0700176 return false;
177 }
178
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700179 final MacAddress other = (MacAddress) o;
alshabibc4901cd2014-09-05 16:50:40 -0700180 return Arrays.equals(this.address, other.address);
181 }
182
183 @Override
184 public int hashCode() {
185 return Arrays.hashCode(this.address);
186 }
187
188 @Override
189 public String toString() {
190 final StringBuilder builder = new StringBuilder();
191 for (final byte b : this.address) {
192 if (builder.length() > 0) {
193 builder.append(":");
194 }
195 builder.append(String.format("%02X", b & 0xFF));
196 }
197 return builder.toString();
198 }
199
200 /**
201 * @return MAC address in string representation without colons (useful for
202 * radix tree storage)
203 */
204 public String toStringNoColon() {
205 final StringBuilder builder = new StringBuilder();
206 for (final byte b : this.address) {
207 builder.append(String.format("%02X", b & 0xFF));
208 }
209 return builder.toString();
210 }
211
212 public byte[] getAddress() {
213 return this.address;
214 }
215}