blob: 8b2bc53f2e875f21deb0a93a1d28ec3251867704 [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
Yotam Harcholf3f11152013-09-05 16:47:16 -070023 public static final MacAddress NO_MASK = MacAddress.of(0xFFFFFFFFFFFFFFFFl);
24 public static final MacAddress FULL_MASK = MacAddress.of(0x0);
25
26 private MacAddress(final long rawValue) {
27 this.rawValue = rawValue;
28 }
29
30 public static MacAddress of(final byte[] address) {
31 long raw =
32 (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32
33 | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16
34 | (address[4] & 0xFFL) << 8 | (address[5] & 0xFFL);
35 return MacAddress.of(raw);
36 }
37
38 public static MacAddress of(final long raw) {
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070039 if(raw == NONE_VAL)
40 return NONE;
41
Yotam Harcholf3f11152013-09-05 16:47:16 -070042 return new MacAddress(raw);
43 }
44
45 public static MacAddress of(final String string) {
46 int index = 0;
47 int shift = 40;
48
49 long raw = 0;
50 if (string.length() != 6 * 2 + 5)
51 throw new IllegalArgumentException("Mac address not well formed: " + string);
52
53 while (shift >= 0) {
54 raw |=
55 ((long) (Character.digit(string.charAt(index++), 16) << 4 | Character
56 .digit(string.charAt(index++), 16))) << shift;
57
58 if (shift == 0)
59 break;
60 if (string.charAt(index++) != ':')
61 throw new IllegalArgumentException("Mac address not well formed: " + string);
62 shift -= 8;
63 }
64 return MacAddress.of(raw);
65 }
66
67 volatile byte[] bytesCache = null;
68
69 public byte[] getBytes() {
70 if (bytesCache == null) {
71 synchronized (this) {
72 if (bytesCache == null) {
73 bytesCache =
74 new byte[] { (byte) ((rawValue >> 40) & 0xFF),
75 (byte) ((rawValue >> 32) & 0xFF),
76 (byte) ((rawValue >> 24) & 0xFF),
77 (byte) ((rawValue >> 16) & 0xFF),
78 (byte) ((rawValue >> 8) & 0xFF),
79 (byte) ((rawValue >> 0) & 0xFF) };
80 }
81 }
82 }
83 return bytesCache;
84 }
85
86 @Override
87 public int getLength() {
88 return MacAddrLen;
89 }
90
91 @Override
92 public String toString() {
93 return HexString.toHexString(rawValue, 6);
94 }
95
96 @Override
97 public int hashCode() {
98 final int prime = 31;
99 int result = 1;
100 result = prime * result + (int) (rawValue ^ (rawValue >>> 32));
101 return result;
102 }
103
104 @Override
105 public boolean equals(final Object obj) {
106 if (this == obj)
107 return true;
108 if (obj == null)
109 return false;
110 if (getClass() != obj.getClass())
111 return false;
112 MacAddress other = (MacAddress) obj;
113 if (rawValue != other.rawValue)
114 return false;
115 return true;
116 }
117
118 public long getLong() {
119 return rawValue;
120 }
121
122 public void write6Bytes(ChannelBuffer c) {
123 c.writeInt((int) (this.rawValue >> 16));
124 c.writeShort((int) this.rawValue & 0xFFFF);
125 }
126
127 public static MacAddress read6Bytes(ChannelBuffer c) throws OFParseError {
128 long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort();
129 return MacAddress.of(raw);
130 }
131
132 @Override
133 public MacAddress applyMask(MacAddress mask) {
134 return MacAddress.of(this.rawValue & mask.rawValue);
135 }
136
Andreas Wundsam85c961f2013-09-29 21:22:12 -0700137 @Override
138 public int compareTo(MacAddress o) {
139 return Longs.compare(rawValue, o.rawValue);
140 }
141
Andreas Wundsam22ba3af2013-10-04 16:00:30 -0700142 @Override
143 public void putTo(PrimitiveSink sink) {
144 sink.putInt((int) (this.rawValue >> 16));
145 sink.putShort((short) (this.rawValue & 0xFFFF));
146 }
147
Yotam Harcholf3f11152013-09-05 16:47:16 -0700148
149
150}