Added cubby-holes for new projects.
diff --git a/of-save/lib/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java b/of-save/lib/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
new file mode 100644
index 0000000..d7f044e
--- /dev/null
+++ b/of-save/lib/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
@@ -0,0 +1,207 @@
+package org.projectfloodlight.openflow.types;
+
+import java.util.Arrays;
+
+import javax.annotation.Nonnull;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+import org.projectfloodlight.openflow.util.HexString;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.Longs;
+
+/**
+ * Wrapper around a 6 byte mac address.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+
+public class MacAddress implements OFValueType<MacAddress> {
+ static final int MacAddrLen = 6;
+ private final long rawValue;
+
+ private final static long NONE_VAL = 0x0L;
+ public static final MacAddress NONE = new MacAddress(NONE_VAL);
+
+ private final static long BROADCAST_VAL = 0x0000FFFFFFFFFFFFL;
+ public static final MacAddress BROADCAST = new MacAddress(BROADCAST_VAL);
+
+ public static final MacAddress NO_MASK = MacAddress.of(0xFFFFFFFFFFFFFFFFl);
+ public static final MacAddress FULL_MASK = MacAddress.of(0x0);
+
+ private static final long LLDP_MAC_ADDRESS_MASK = 0xfffffffffff0L;
+ private static final long LLDP_MAC_ADDRESS_VALUE = 0x0180c2000000L;
+
+ private MacAddress(final long rawValue) {
+ this.rawValue = rawValue;
+ }
+
+ public static MacAddress of(final byte[] address) {
+ if (address.length != MacAddrLen)
+ throw new IllegalArgumentException(
+ "Mac address byte array must be exactly 6 bytes long; length = " + address.length);
+ long raw =
+ (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32
+ | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16
+ | (address[4] & 0xFFL) << 8 | (address[5] & 0xFFL);
+ return MacAddress.of(raw);
+ }
+
+ public static MacAddress of(long raw) {
+ raw &= BROADCAST_VAL;
+ if(raw == NONE_VAL)
+ return NONE;
+ if (raw == BROADCAST_VAL)
+ return BROADCAST;
+ return new MacAddress(raw);
+ }
+
+ /** Parse a mac adress from the canonical string representation as
+ * 6 hex bytes separated by colons (01:02:03:04:05:06).
+ *
+ * @param macString - a mac address in canonical string representation
+ * @return the parsed MacAddress
+ * @throws IllegalArgumentException if macString is not a valid mac adddress
+ */
+ @Nonnull
+ public static MacAddress of(@Nonnull final String macString) throws IllegalArgumentException {
+ if (macString == null) {
+ throw new NullPointerException("macString must not be null");
+ }
+ int index = 0;
+ int shift = 40;
+ final String FORMAT_ERROR = "Mac address is not well-formed. " +
+ "It must consist of 6 hex digit pairs separated by colons: ";
+
+ long raw = 0;
+ if (macString.length() != 6 * 2 + 5)
+ throw new IllegalArgumentException(FORMAT_ERROR + macString);
+
+ while (shift >= 0) {
+ int digit1 = Character.digit(macString.charAt(index++), 16);
+ int digit2 = Character.digit(macString.charAt(index++), 16);
+ if ((digit1 < 0) || (digit2 < 0))
+ throw new IllegalArgumentException(FORMAT_ERROR + macString);
+ raw |= ((long) (digit1 << 4 | digit2)) << shift;
+
+ if (shift == 0)
+ break;
+ if (macString.charAt(index++) != ':')
+ throw new IllegalArgumentException(FORMAT_ERROR + macString);
+ shift -= 8;
+ }
+ return MacAddress.of(raw);
+ }
+
+ private volatile byte[] bytesCache = null;
+
+ public byte[] getBytes() {
+ if (bytesCache == null) {
+ synchronized (this) {
+ if (bytesCache == null) {
+ bytesCache =
+ new byte[] { (byte) ((rawValue >> 40) & 0xFF),
+ (byte) ((rawValue >> 32) & 0xFF),
+ (byte) ((rawValue >> 24) & 0xFF),
+ (byte) ((rawValue >> 16) & 0xFF),
+ (byte) ((rawValue >> 8) & 0xFF),
+ (byte) ((rawValue >> 0) & 0xFF) };
+ }
+ }
+ }
+ return Arrays.copyOf(bytesCache, bytesCache.length);
+ }
+
+ /**
+ * Returns {@code true} if the MAC address is the broadcast address.
+ * @return {@code true} if the MAC address is the broadcast address.
+ */
+ public boolean isBroadcast() {
+ return this == BROADCAST;
+ }
+
+ /**
+ * Returns {@code true} if the MAC address is a multicast address.
+ * @return {@code true} if the MAC address is a multicast address.
+ */
+ public boolean isMulticast() {
+ if (isBroadcast()) {
+ return false;
+ }
+ return (rawValue & (0x01L << 40)) != 0;
+ }
+
+ /**
+ * Returns {@code true} if the MAC address is an LLDP mac address.
+ * @return {@code true} if the MAC address is an LLDP mac address.
+ */
+ public boolean isLLDPAddress() {
+ return (rawValue & LLDP_MAC_ADDRESS_MASK) == LLDP_MAC_ADDRESS_VALUE;
+ }
+
+ @Override
+ public int getLength() {
+ return MacAddrLen;
+ }
+
+ @Override
+ public String toString() {
+ return HexString.toHexString(rawValue, 6);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (rawValue ^ (rawValue >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ MacAddress other = (MacAddress) obj;
+ if (rawValue != other.rawValue)
+ return false;
+ return true;
+ }
+
+ public long getLong() {
+ return rawValue;
+ }
+
+ public void write6Bytes(ChannelBuffer c) {
+ c.writeInt((int) (this.rawValue >> 16));
+ c.writeShort((int) this.rawValue & 0xFFFF);
+ }
+
+ public static MacAddress read6Bytes(ChannelBuffer c) throws OFParseError {
+ long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort();
+ return MacAddress.of(raw);
+ }
+
+ @Override
+ public MacAddress applyMask(MacAddress mask) {
+ return MacAddress.of(this.rawValue & mask.rawValue);
+ }
+
+ @Override
+ public int compareTo(MacAddress o) {
+ return Longs.compare(rawValue, o.rawValue);
+ }
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt((int) (this.rawValue >> 16));
+ sink.putShort((short) (this.rawValue & 0xFFFF));
+ }
+
+
+
+}