fixing loxi output
upgrade to 0.3.8
agrregate pom for of-lib

Change-Id: Ie75d75b708c30934bbca235e68c50de656d84ad4
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
index f103230..78e6075 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
@@ -232,6 +232,9 @@
     public final static MatchField<U16> BSN_TCP_FLAGS =
             new MatchField<U16>("bsn_tcp_flags", MatchFields.BSN_TCP_FLAGS);
 
+    public final static MatchField<ClassId> BSN_VLAN_XLATE_PORT_GROUP_ID =
+            new MatchField<ClassId>("bsn_vlan_xlate_port_group_id", MatchFields.BSN_VLAN_XLATE_PORT_GROUP_ID);
+
     public String getName() {
         return name;
     }
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
index 354a528..863634e 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
@@ -56,4 +56,5 @@
     BSN_UDF6,
     BSN_UDF7,
     BSN_TCP_FLAGS,
+    BSN_VLAN_XLATE_PORT_GROUP_ID,
 }
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
index 1dd55d5..3030e3e 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
@@ -17,6 +17,23 @@
      */
     int prefixBits(int numBits);
 
+    /** perform an arithmetic addition of this value and other. Wraps around on
+     * overflow of the defined word size.
+     *
+     * @param other
+     * @return this + other
+     */
+    H add(H other);
+
+    /**
+     * arithmetically substract the given 'other' value from this value.
+     * around on overflow.
+     *
+     * @param other
+     * @return this - other
+     */
+    H subtract(H other);
+
     /** @return the bitwise inverse of this value */
     H inverse();
 
@@ -29,26 +46,57 @@
     /** xor this value with another value value of the same type */
     H xor(H other);
 
-    /** calculate a combined hash value of this hash value (the <b>Key</b>) and the hash value
-     *  specified as a parameter (the <b>Value</b>).
-     *  <p>
-     *  The value is constructed as follows:
-     *  <ul>
-     *   <li>the first keyBits bits are taken only from the Key
-     *   <li>the other bits are taken from key xor value.
-     *  </ul>
-     *  The overall result looks like this:
-     *  <pre>
-     *  MSB                      LSB
-     *   +---------+--------------+
-     *   | key     | key ^ value  |
-     *   +---------+--------------+
-     *   |-keyBits-|
-     *  </pre>
+    /** create and return a builder */
+    Builder<H> builder();
+
+    /** a mutator for HashValues. Allows perfomring a series of
+     *  operations on a hashv value without the associated cost of object
+     *  reallocation.
      *
-     * @param value - hash value to be compared with this value (the key)
-     * @param keyBits number of prefix bits that are just taken from key
-     * @return the combined value.
+     * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+     *
+     * @param <H> - the hashvalue
      */
-    H combineWithValue(H value, int keyBits);
+    public interface Builder<H> {
+        /** perform an arithmetic addition of this value and other. Wraps around on
+         * overflow of the defined word size.
+         *
+         * @param other
+         * @return this mutator
+         */
+        Builder<H> add(H other);
+
+        /**
+         * arithmetically substract the given 'other' value from the value stored in this mutator.
+         * around on overflow.
+         *
+         * @param other
+         * @return this mutator
+         */
+        Builder<H> subtract(H other);
+
+        /** bitwise invert the value stored in this mutator
+         *
+         * @return this mutator
+         */
+        Builder<H> invert();
+
+        /** or the value stored in this mutator with another value value of the same type
+        * @return this mutator
+        */
+        Builder<H> or(H other);
+
+        /** and the value stored in this mutator with another value value of the same type
+        * @return this mutator
+        */
+        Builder<H> and(H other);
+
+        /** xor the value stored in this mutator with another value value of the same type
+        * @return this mutator
+        */
+        Builder<H> xor(H other);
+
+        /** @return the hash value */
+        public H build();
+    }
 }
\ No newline at end of file
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
index 5e4e818..cee9ad1 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
@@ -10,6 +10,11 @@
 
 public abstract class IPAddress<F extends IPAddress<F>> implements OFValueType<F> {
 
+    /**
+     * Returns the Internet Protocol (IP) version of this object
+     *
+     * @return  the Internet Protocol (IP) version of this object
+     */
     public abstract IPVersion getIpVersion();
 
     /**
@@ -55,6 +60,52 @@
      */
     public abstract F not();
 
+    /**
+     * Returns an {@code IPAddressWithMask<F>} object that represents this
+     * IP address masked by the given IP address mask.
+     *
+     * @param mask  the {@code F} object that represents the mask
+     * @return      an {@code IPAddressWithMask<F>} object that represents this
+     *              IP address masked by the given mask
+     * @throws NullPointerException  if the given mask was {@code null}
+     */
+    @Nonnull
+    public abstract IPAddressWithMask<F> withMask(@Nonnull final F mask);
+
+    /**
+     * Returns an {@code IPAddressWithMask<F>} object that represents this
+     * IP address masked by the CIDR subnet mask of the given prefix length.
+     *
+     * @param cidrMaskLength  the prefix length of the CIDR subnet mask
+     *                        (i.e. the number of leading one-bits),
+     *                        where <code>
+     *                        0 <= cidrMaskLength <= (F.getLength() * 8)
+     *                        </code>
+     * @return                an {@code IPAddressWithMask<F>} object that
+     *                        represents this IP address masked by the CIDR
+     *                        subnet mask of the given prefix length
+     * @throws IllegalArgumentException  if the given prefix length was invalid
+     * @see #ofCidrMaskLength(int)
+     */
+    @Nonnull
+    public abstract IPAddressWithMask<F> withMaskOfLength(
+            final int cidrMaskLength);
+
+    /**
+     * Returns the raw IP address of this {@code IPAddress} object. The result
+     * is in network byte order: the highest order byte of the address is in
+     * {@code getBytes()[0]}.
+     * <p>
+     * Similar to {@link InetAddress#getAddress()}
+     *
+     * @return  the raw IP address of this object
+     * @see InetAddress#getAddress()
+     */
+    public abstract byte[] getBytes();
+
+    @Override
+    public abstract String toString();
+
     @Override
     public abstract boolean equals(Object other);
 
@@ -88,14 +139,26 @@
      * @throws NullPointerException if address is null
      */
     @Nonnull
-    public static IPAddress<?> fromInetAddress(@Nonnull InetAddress address) {
+    public static IPAddress<?> of(@Nonnull InetAddress address) {
         Preconditions.checkNotNull(address, "address must not be null");
-        byte [] bytes = address.getAddress();
         if(address instanceof Inet4Address)
-            return IPv4Address.of(bytes);
+            return IPv4Address.of((Inet4Address) address);
         else if (address instanceof Inet6Address)
-            return IPv6Address.of(bytes);
+            return IPv6Address.of((Inet6Address) address);
         else
             return IPAddress.of(address.getHostAddress());
     }
+
+    /**
+     * Factory function for InetAddress values.
+     * @param address the InetAddress you wish to parse into an IPAddress object.
+     * @return the IPAddress object.
+     * @throws NullPointerException if address is null
+     * @deprecated  replaced by {@link #of(InetAddress)}
+     */
+    @Deprecated
+    @Nonnull
+    public static IPAddress<?> fromInetAddress(@Nonnull InetAddress address) {
+        return of(address);
+    }
 }
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
index ba7eb93..7cd8099 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
@@ -1,5 +1,7 @@
 package org.projectfloodlight.openflow.types;
 
+import com.google.common.base.Preconditions;
+
 
 public abstract class IPAddressWithMask<F extends IPAddress<F>> extends Masked<F> {
 
@@ -8,6 +10,8 @@
     }
 
     public abstract IPVersion getIpVersion();
+    
+    public abstract boolean contains(IPAddress<?> ip);
 
     public F getSubnetBroadcastAddress() {
         if (!mask.isCidrMask()) {
@@ -22,9 +26,8 @@
     }
 
     public static IPAddressWithMask<?> of(String ip) {
-        if (ip == null) {
-            throw new NullPointerException("String ip must not be null");
-        }
+        Preconditions.checkNotNull(ip, "string ip must not be null");
+
         if (ip.indexOf('.') != -1)
             return IPv4AddressWithMask.of(ip);
         else if (ip.indexOf(':') != -1)
@@ -49,5 +52,4 @@
 
         return res.toString();
     }
-
 }
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
index 865fb79..3a1b15e 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
@@ -1,11 +1,14 @@
 package org.projectfloodlight.openflow.types;
 
+import java.net.Inet4Address;
+import java.net.InetAddress;
 import java.util.Arrays;
 
 import javax.annotation.Nonnull;
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.base.Preconditions;
 import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
@@ -78,19 +81,17 @@
 
     @Override
     public IPv4Address and(IPv4Address other) {
-        if (other == null) {
-            throw new NullPointerException("Other IP Address must not be null");
-        }
-        IPv4Address otherIp = (IPv4Address) other;
+        Preconditions.checkNotNull(other, "other must not be null");
+
+        IPv4Address otherIp = other;
         return IPv4Address.of(rawValue & otherIp.rawValue);
     }
 
     @Override
     public IPv4Address or(IPv4Address other) {
-        if (other == null) {
-            throw new NullPointerException("Other IP Address must not be null");
-        }
-        IPv4Address otherIp = (IPv4Address) other;
+        Preconditions.checkNotNull(other, "other must not be null");
+
+        IPv4Address otherIp = other;
         return IPv4Address.of(rawValue | otherIp.rawValue);
     }
 
@@ -99,13 +100,30 @@
         return IPv4Address.of(~rawValue);
     }
 
-    public static IPv4Address of(final byte[] address) {
-        if (address == null) {
-            throw new NullPointerException("Address must not be null");
-        }
+    /**
+     * Returns an {@code IPv4Address} object that represents the given
+     * IP address. The argument is in network byte order: the highest
+     * order byte of the address is in {@code address[0]}.
+     * <p>
+     * The address byte array must be 4 bytes long (32 bits long).
+     * <p>
+     * Similar to {@link InetAddress#getByAddress(byte[])}.
+     *
+     * @param address  the raw IP address in network byte order
+     * @return         an {@code IPv4Address} object that represents the given
+     *                 raw IP address
+     * @throws NullPointerException      if the given address was {@code null}
+     * @throws IllegalArgumentException  if the given address was of an invalid
+     *                                   byte array length
+     * @see InetAddress#getByAddress(byte[])
+     */
+    @Nonnull
+    public static IPv4Address of(@Nonnull final byte[] address) {
+        Preconditions.checkNotNull(address, "address must not be null");
+
         if (address.length != LENGTH) {
             throw new IllegalArgumentException(
-                    "Invalid byte array length for IPv4Address address: " + address.length);
+                    "Invalid byte array length for IPv4 address: " + address.length);
         }
 
         int raw =
@@ -114,30 +132,37 @@
         return IPv4Address.of(raw);
     }
 
-    /** construct an IPv4Address from a 32-bit integer value.
+    /**
+     * Returns an {@code IPv4Address} object that represents the given
+     * IP address.
      *
-     * @param raw the IPAdress represented as a 32-bit integer
-     * @return the constructed IPv4Address
+     * @param raw  the raw IP address represented as a 32-bit integer
+     * @return     an {@code IPv4Address} object that represents the given
+     *             raw IP address
      */
+    @Nonnull
     public static IPv4Address of(final int raw) {
         if(raw == NONE_VAL)
             return NONE;
         return new IPv4Address(raw);
     }
 
-    /** parse an IPv4Address from the canonical dotted-quad representation
-     * (1.2.3.4).
+    /**
+     * Returns an {@code IPv4Address} object that represents the given
+     * IP address. The argument is in the canonical quad-dotted notation.
+     * For example, {@code 1.2.3.4}.
      *
-     * @param string an IPv4 address in dotted-quad representation
-     * @return the parsed IPv4 address
-     * @throws NullPointerException if string is null
-     * @throws IllegalArgumentException if string is not a valid IPv4Address
+     * @param string  the IP address in the canonical quad-dotted notation
+     * @return        an {@code IPv4Address} object that represents the given
+     *                IP address
+     * @throws NullPointerException      if the given string was {@code null}
+     * @throws IllegalArgumentException  if the given string was not a valid
+     *                                   IPv4 address
      */
     @Nonnull
     public static IPv4Address of(@Nonnull final String string) throws IllegalArgumentException {
-        if (string == null) {
-            throw new NullPointerException("String must not be null");
-        }
+        Preconditions.checkNotNull(string, "string must not be null");
+
         int start = 0;
         int shift = 24;
 
@@ -161,12 +186,90 @@
         return IPv4Address.of(raw);
     }
 
+    /**
+     * Returns an {@code IPv4Address} object that represents the given
+     * IP address. The argument is given as an {@code Inet4Address} object.
+     *
+     * @param address  the IP address as an {@code Inet4Address} object
+     * @return         an {@code IPv4Address} object that represents the
+     *                 given IP address
+     * @throws NullPointerException  if the given {@code Inet4Address} was
+     *                               {@code null}
+     */
+    @Nonnull
+    public static IPv4Address of(@Nonnull final Inet4Address address) {
+        Preconditions.checkNotNull(address, "address must not be null");
+        return IPv4Address.of(address.getAddress());
+    }
+
+    /**
+     * Returns an {@code IPv4Address} object that represents the
+     * CIDR subnet mask of the given prefix length.
+     *
+     * @param cidrMaskLength  the prefix length of the CIDR subnet mask
+     *                        (i.e. the number of leading one-bits),
+     *                        where {@code 0 <= cidrMaskLength <= 32}
+     * @return                an {@code IPv4Address} object that represents the
+     *                        CIDR subnet mask of the given prefix length
+     * @throws IllegalArgumentException  if the given prefix length was invalid
+     */
+    @Nonnull
+    public static IPv4Address ofCidrMaskLength(final int cidrMaskLength) {
+        Preconditions.checkArgument(
+                cidrMaskLength >= 0 && cidrMaskLength <= 32,
+                "Invalid IPv4 CIDR mask length: %s", cidrMaskLength);
+
+        if (cidrMaskLength == 32) {
+            return IPv4Address.NO_MASK;
+        } else if (cidrMaskLength == 0) {
+            return IPv4Address.FULL_MASK;
+        } else {
+            int mask = (-1) << (32 - cidrMaskLength);
+            return IPv4Address.of(mask);
+        }
+    }
+
+    /**
+     * Returns an {@code IPv4AddressWithMask} object that represents this
+     * IP address masked by the given IP address mask.
+     *
+     * @param mask  the {@code IPv4Address} object that represents the mask
+     * @return      an {@code IPv4AddressWithMask} object that represents this
+     *              IP address masked by the given mask
+     * @throws NullPointerException  if the given mask was {@code null}
+     */
+    @Nonnull
+    @Override
+    public IPv4AddressWithMask withMask(@Nonnull final IPv4Address mask) {
+        return IPv4AddressWithMask.of(this, mask);
+    }
+
+    /**
+     * Returns an {@code IPv4AddressWithMask} object that represents this
+     * IP address masked by the CIDR subnet mask of the given prefix length.
+     *
+     * @param cidrMaskLength  the prefix length of the CIDR subnet mask
+     *                        (i.e. the number of leading one-bits),
+     *                        where {@code 0 <= cidrMaskLength <= 32}
+     * @return                an {@code IPv4AddressWithMask} object that
+     *                        represents this IP address masked by the CIDR
+     *                        subnet mask of the given prefix length
+     * @throws IllegalArgumentException  if the given prefix length was invalid
+     * @see #ofCidrMaskLength(int)
+     */
+    @Nonnull
+    @Override
+    public IPv4AddressWithMask withMaskOfLength(final int cidrMaskLength) {
+        return this.withMask(IPv4Address.ofCidrMaskLength(cidrMaskLength));
+    }
+
     public int getInt() {
         return rawValue;
     }
 
     private volatile byte[] bytesCache = null;
 
+    @Override
     public byte[] getBytes() {
         if (bytesCache == null) {
             synchronized (this) {
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
index 9b60c6a..b6dc1b9 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
@@ -1,5 +1,9 @@
 package org.projectfloodlight.openflow.types;
 
+import javax.annotation.Nonnull;
+
+import com.google.common.base.Preconditions;
+
 
 public class IPv4AddressWithMask extends IPAddressWithMask<IPv4Address> {
     public final static IPv4AddressWithMask NONE = of(IPv4Address.NONE, IPv4Address.NONE);
@@ -17,27 +21,77 @@
         return IPVersion.IPv4;
     }
 
-    public static IPv4AddressWithMask of(int rawValue, int rawMask) {
+    /**
+     * Returns an {@code IPv4AddressWithMask} object that represents the given
+     * raw IP address masked by the given raw IP address mask.
+     *
+     * @param rawValue  the raw IP address to be masked
+     * @param rawMask   the raw IP address mask
+     * @return          an {@code IPv4AddressWithMask} object that represents
+     *                  the given raw IP address masked by the given raw IP
+     *                  address mask
+     * @deprecated      replaced by {@link IPv4Address#of(int)} and
+     *                  {@link IPv4Address#withMask(IPv4Address), e.g. <code>
+     *                  IPv4Address.of(int).withMask(IPv4Address.of(int))
+     *                  </code>
+     */
+    @Nonnull
+    @Deprecated
+    public static IPv4AddressWithMask of(final int rawValue, final int rawMask) {
         return new IPv4AddressWithMask(rawValue, rawMask);
     }
 
-    public static IPv4AddressWithMask of(IPv4Address value, IPv4Address mask) {
-        if (value == null) {
-            throw new NullPointerException("Value must not be null");
-        }
-        if (mask == null) {
-            throw new NullPointerException("Mask must not be null");
-        }
+    /**
+     * Returns an {@code IPv4AddressWithMask} object that represents the given
+     * IP address masked by the given IP address mask. Both arguments are given
+     * as {@code IPv4Address} objects.
+     *
+     * @param value  the IP address to be masked
+     * @param mask   the IP address mask
+     * @return       an {@code IPv4AddressWithMask} object that represents
+     *               the given IP address masked by the given IP address mask
+     * @throws NullPointerException  if any of the given {@code IPv4Address}
+     *                               objects were {@code null}
+     */
+    @Nonnull
+    public static IPv4AddressWithMask of(
+            @Nonnull final IPv4Address value,
+            @Nonnull final IPv4Address mask) {
+        Preconditions.checkNotNull(value, "value must not be null");
+        Preconditions.checkNotNull(mask, "mask must not be null");
+
         return new IPv4AddressWithMask(value, mask);
     }
 
-    public static IPv4AddressWithMask of(final String string) {
-        if (string == null) {
-            throw new NullPointerException("String must not be null");
-        }
+    /**
+     * Returns an {@code IPv4AddressWithMask} object that corresponds to
+     * the given string in CIDR notation or other acceptable notations.
+     * <p>
+     * The following notations are accepted.
+     * <table><tr>
+     * <th>Notation</th><th>Example</th><th>Notes</th>
+     * </tr><tr>
+     * <td>IPv4 address only</td><td>{@code 1.2.3.4}</td><td>The subnet mask of
+     * prefix length 32 (i.e. {@code 255.255.255.255}) is assumed.</td>
+     * </tr><tr>
+     * <td>IPv4 address/mask</td><td>{@code 1.2.3.4/255.255.255.0}</td>
+     * </tr><tr>
+     * <td>CIDR notation</td><td>{@code 1.2.3.4/24}</td>
+     * </tr></table>
+     *
+     * @param string  the string in acceptable notations
+     * @return        an {@code IPv4AddressWithMask} object that corresponds to
+     *                the given string in acceptable notations
+     * @throws NullPointerException      if the given string was {@code null}
+     * @throws IllegalArgumentException  if the given string was malformed
+     */
+    @Nonnull
+    public static IPv4AddressWithMask of(@Nonnull final String string) {
+        Preconditions.checkNotNull(string, "string must not be null");
+
         int slashPos;
         String ip = string;
-        int maskBits = 32;
+        int cidrMaskLength = 32;
         IPv4Address maskAddress = null;
 
         // Read mask suffix
@@ -52,14 +106,11 @@
                     maskAddress = IPv4Address.of(suffix);
                 } else {
                     // CIDR Suffix
-                    maskBits = Integer.parseInt(suffix);
+                    cidrMaskLength = Integer.parseInt(suffix);
                 }
             } catch (NumberFormatException e) {
                 throw new IllegalArgumentException("IP Address not well formed: " + string);
             }
-            if (maskBits < 0 || maskBits > 32) {
-                throw new IllegalArgumentException("IP Address not well formed: " + string);
-            }
         }
 
         // Read IP
@@ -68,17 +119,21 @@
         if (maskAddress != null) {
             // Full address mask
             return IPv4AddressWithMask.of(ipv4, maskAddress);
-        } else if (maskBits == 32) {
-            // No mask
-            return IPv4AddressWithMask.of(ipv4, IPv4Address.NO_MASK);
-        } else if (maskBits == 0) {
-            // No mask
-            return IPv4AddressWithMask.of(ipv4, IPv4Address.FULL_MASK);
         } else {
-            // With mask
-            int mask = (-1) << (32 - maskBits);
-            return IPv4AddressWithMask.of(ipv4, IPv4Address.of(mask));
+            return IPv4AddressWithMask.of(
+                    ipv4, IPv4Address.ofCidrMaskLength(cidrMaskLength));
         }
     }
 
+    @Override
+    public boolean contains(IPAddress<?> ip) {
+        Preconditions.checkNotNull(ip, "ip must not be null");
+
+        if(ip.getIpVersion() == IPVersion.IPv4) {
+            IPv4Address ipv4 = (IPv4Address) ip;
+            return this.matches(ipv4);
+        }
+
+        return false;
+    }
 }
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
index 83fb31a..471d0fb 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
@@ -1,5 +1,7 @@
 package org.projectfloodlight.openflow.types;
 
+import java.net.Inet6Address;
+import java.net.InetAddress;
 import java.util.Arrays;
 import java.util.regex.Pattern;
 
@@ -8,6 +10,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.base.Preconditions;
 import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Longs;
 
@@ -102,19 +105,17 @@
 
     @Override
     public IPv6Address and(IPv6Address other) {
-        if (other == null) {
-            throw new NullPointerException("Other IP Address must not be null");
-        }
-        IPv6Address otherIp = (IPv6Address) other;
+        Preconditions.checkNotNull(other, "other must not be null");
+
+        IPv6Address otherIp = other;
         return IPv6Address.of((raw1 & otherIp.raw1), (raw2 & otherIp.raw2));
     }
 
     @Override
     public IPv6Address or(IPv6Address other) {
-        if (other == null) {
-            throw new NullPointerException("Other IP Address must not be null");
-        }
-        IPv6Address otherIp = (IPv6Address) other;
+        Preconditions.checkNotNull(other, "other must not be null");
+
+        IPv6Address otherIp = other;
         return IPv6Address.of((raw1 | otherIp.raw1), (raw2 | otherIp.raw2));
     }
 
@@ -123,10 +124,27 @@
         return IPv6Address.of(~raw1, ~raw2);
     }
 
-    public static IPv6Address of(final byte[] address) {
-        if (address == null) {
-            throw new NullPointerException("Address must not be null");
-        }
+    /**
+     * Returns an {@code IPv6Address} object that represents the given
+     * IP address. The argument is in network byte order: the highest
+     * order byte of the address is in {@code address[0]}.
+     * <p>
+     * The address byte array must be 16 bytes long (128 bits long).
+     * <p>
+     * Similar to {@link InetAddress#getByAddress(byte[])}.
+     *
+     * @param address  the raw IP address in network byte order
+     * @return         an {@code IPv6Address} object that represents the given
+     *                 raw IP address
+     * @throws NullPointerException      if the given address was {@code null}
+     * @throws IllegalArgumentException  if the given address was of an invalid
+     *                                   byte array length
+     * @see InetAddress#getByAddress(byte[])
+     */
+    @Nonnull
+    public static IPv6Address of(@Nonnull final byte[] address) {
+        Preconditions.checkNotNull(address, "address must not be null");
+
         if (address.length != LENGTH) {
             throw new IllegalArgumentException(
                     "Invalid byte array length for IPv6 address: " + address.length);
@@ -171,25 +189,30 @@
 
     private final static Pattern colonPattern = Pattern.compile(":");
 
-    /** parse an IPv6Address from its conventional string representation.
-     *  <p>
-     *  Expects up to 8 groups of 16-bit hex words seperated by colons
-     *  (e.g., 2001:db8:85a3:8d3:1319:8a2e:370:7348).
-     *  <p>
-     *  Supports zero compression (e.g., 2001:db8::7348).
-     *  Does <b>not</b> currently support embedding a dotted-quad IPv4 address
-     *  into the IPv6 address (e.g., 2001:db8::192.168.0.1).
+    /**
+     * Returns an {@code IPv6Address} object that represents the given
+     * IP address. The argument is in the conventional string representation
+     * of IPv6 addresses.
+     * <p>
+     * Expects up to 8 groups of 16-bit hex words seperated by colons
+     * (e.g., 2001:db8:85a3:8d3:1319:8a2e:370:7348).
+     * <p>
+     * Supports zero compression (e.g., 2001:db8::7348).
+     * Does <b>not</b> currently support embedding a dotted-quad IPv4 address
+     * into the IPv6 address (e.g., 2001:db8::192.168.0.1).
      *
-     * @param string a string representation of an IPv6 address
-     * @return the parsed IPv6 address
-     * @throws NullPointerException if string is null
-     * @throws IllegalArgumentException if string is not a valid IPv6Address
+     * @param string  the IP address in the conventional string representation
+     *                of IPv6 addresses
+     * @return        an {@code IPv6Address} object that represents the given
+     *                IP address
+     * @throws NullPointerException      if the given string was {@code null}
+     * @throws IllegalArgumentException  if the given string was not a valid
+     *                                   IPv6 address
      */
     @Nonnull
     public static IPv6Address of(@Nonnull final String string) throws IllegalArgumentException {
-        if (string == null) {
-            throw new NullPointerException("String must not be null");
-        }
+        Preconditions.checkNotNull(string, "string must not be null");
+
         IPv6Builder builder = new IPv6Builder();
         String[] parts = colonPattern.split(string, -1);
 
@@ -242,19 +265,104 @@
         return builder.getIPv6();
     }
 
-    /** construct an IPv6 adress from two 64 bit integers representing the first and
-     *  second 8-byte blocks of the address.
+    /**
+     * Returns an {@code IPv6Address} object that represents the given
+     * IP address. The arguments are the two 64-bit integers representing
+     * the first (higher-order) and second (lower-order) 64-bit blocks
+     * of the IP address.
      *
-     * @param raw1 - the first 8 byte block of the address
-     * @param raw2 - the second 8 byte block of the address
-     * @return the constructed IPv6Address
+     * @param raw1  the first (higher-order) 64-bit block of the IP address
+     * @param raw2  the second (lower-order) 64-bit block of the IP address
+     * @return      an {@code IPv6Address} object that represents the given
+     *              raw IP address
      */
+    @Nonnull
     public static IPv6Address of(final long raw1, final long raw2) {
         if(raw1==NONE_VAL1 && raw2 == NONE_VAL2)
             return NONE;
         return new IPv6Address(raw1, raw2);
     }
 
+    /**
+     * Returns an {@code IPv6Address} object that represents the given
+     * IP address. The argument is given as an {@code Inet6Address} object.
+     *
+     * @param address  the IP address as an {@code Inet6Address} object
+     * @return         an {@code IPv6Address} object that represents the
+     *                 given IP address
+     * @throws NullPointerException  if the given {@code Inet6Address} was
+     *                               {@code null}
+     */
+    @Nonnull
+    public static IPv6Address of(@Nonnull final Inet6Address address) {
+        Preconditions.checkNotNull(address, "address must not be null");
+        return IPv6Address.of(address.getAddress());
+    }
+
+    /**
+     * Returns an {@code IPv6Address} object that represents the
+     * CIDR subnet mask of the given prefix length.
+     *
+     * @param cidrMaskLength  the prefix length of the CIDR subnet mask
+     *                        (i.e. the number of leading one-bits),
+     *                        where {@code 0 <= cidrMaskLength <= 128}
+     * @return                an {@code IPv6Address} object that represents the
+     *                        CIDR subnet mask of the given prefix length
+     * @throws IllegalArgumentException  if the given prefix length was invalid
+     */
+    @Nonnull
+    public static IPv6Address ofCidrMaskLength(final int cidrMaskLength) {
+        Preconditions.checkArgument(
+                cidrMaskLength >= 0 && cidrMaskLength <= 128,
+                "Invalid IPv6 CIDR mask length: %s", cidrMaskLength);
+
+        if (cidrMaskLength == 128) {
+            return IPv6Address.NO_MASK;
+        } else if (cidrMaskLength == 0) {
+            return IPv6Address.FULL_MASK;
+        } else {
+            int shift1 = Math.min(cidrMaskLength, 64);
+            long raw1 = shift1 == 0 ? 0 : -1L << (64 - shift1);
+            int shift2 = Math.max(cidrMaskLength - 64, 0);
+            long raw2 = shift2 == 0 ? 0 : -1L << (64 - shift2);
+            return IPv6Address.of(raw1, raw2);
+        }
+    }
+
+    /**
+     * Returns an {@code IPv6AddressWithMask} object that represents this
+     * IP address masked by the given IP address mask.
+     *
+     * @param mask  the {@code IPv6Address} object that represents the mask
+     * @return      an {@code IPv6AddressWithMask} object that represents this
+     *              IP address masked by the given mask
+     * @throws NullPointerException  if the given mask was {@code null}
+     */
+    @Nonnull
+    @Override
+    public IPv6AddressWithMask withMask(@Nonnull final IPv6Address mask) {
+        return IPv6AddressWithMask.of(this, mask);
+    }
+
+    /**
+     * Returns an {@code IPv6AddressWithMask} object that represents this
+     * IP address masked by the CIDR subnet mask of the given prefix length.
+     *
+     * @param cidrMaskLength  the prefix length of the CIDR subnet mask
+     *                        (i.e. the number of leading one-bits),
+     *                        where {@code 0 <= cidrMaskLength <= 128}
+     * @return                an {@code IPv6AddressWithMask} object that
+     *                        represents this IP address masked by the CIDR
+     *                        subnet mask of the given prefix length
+     * @throws IllegalArgumentException  if the given prefix length was invalid
+     * @see #ofCidrMaskLength(int)
+     */
+    @Nonnull
+    @Override
+    public IPv6AddressWithMask withMaskOfLength(final int cidrMaskLength) {
+        return this.withMask(IPv6Address.ofCidrMaskLength(cidrMaskLength));
+    }
+
     private volatile byte[] bytesCache = null;
 
     public byte[] getBytes() {
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
index 7259c7f..ee34923 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
@@ -1,7 +1,6 @@
 package org.projectfloodlight.openflow.types;
 
-import java.math.BigInteger;
-import java.util.Arrays;
+import com.google.common.base.Preconditions;
 
 public class IPv6AddressWithMask extends IPAddressWithMask<IPv6Address> {
     public final static IPv6AddressWithMask NONE = of(IPv6Address.NONE, IPv6Address.NONE);
@@ -16,23 +15,17 @@
     }
 
     public static IPv6AddressWithMask of(IPv6Address value, IPv6Address mask) {
-        if (value == null) {
-            throw new NullPointerException("Value must not be null");
-        }
-        if (mask == null) {
-            throw new NullPointerException("Mask must not be null");
-        }
+        Preconditions.checkNotNull(value, "value must not be null");
+        Preconditions.checkNotNull(mask, "mask must not be null");
         return new IPv6AddressWithMask(value, mask);
     }
 
-
     public static IPv6AddressWithMask of(final String string) {
-        if (string == null) {
-            throw new NullPointerException("String must not be null");
-        }
+        Preconditions.checkNotNull(string, "string must not be null");
+
         int slashPos;
         String ip = string;
-        int maskBits = 128;
+        int cidrMaskLength = 128;
         IPv6Address maskAddress = null;
 
         // Read mask suffix
@@ -47,14 +40,11 @@
                     maskAddress = IPv6Address.of(suffix);
                 } else {
                     // CIDR Suffix
-                    maskBits = Integer.parseInt(suffix);
+                    cidrMaskLength = Integer.parseInt(suffix);
                 }
             } catch (NumberFormatException e) {
                 throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
             }
-            if (maskBits < 0 || maskBits > 128) {
-                throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
-            }
         }
 
         // Read IP
@@ -63,30 +53,21 @@
         if (maskAddress != null) {
             // Full address mask
             return IPv6AddressWithMask.of(ipv6, maskAddress);
-        } else if (maskBits == 128) {
-            // No mask
-            return IPv6AddressWithMask.of(ipv6, IPv6Address.NO_MASK);
-        } else if (maskBits == 0) {
-            // Entirely masked out
-            return IPv6AddressWithMask.of(ipv6, IPv6Address.FULL_MASK);
-        }else {
-            // With mask
-            BigInteger mask = BigInteger.ONE.negate().shiftLeft(128 - maskBits);
-            byte[] maskBytesTemp = mask.toByteArray();
-            byte[] maskBytes;
-            if (maskBytesTemp.length < 16) {
-                maskBytes = new byte[16];
-                System.arraycopy(maskBytesTemp, 0, maskBytes, 16 - maskBytesTemp.length, maskBytesTemp.length);
-                Arrays.fill(maskBytes, 0, 16 - maskBytesTemp.length, (byte)(0xFF));
-            } else if (maskBytesTemp.length > 16) {
-                maskBytes = new byte[16];
-                System.arraycopy(maskBytesTemp, 0, maskBytes, 0, maskBytes.length);
-            } else {
-                maskBytes = maskBytesTemp;
-            }
-            return IPv6AddressWithMask.of(ipv6, IPv6Address.of(maskBytes));
+        } else {
+            return IPv6AddressWithMask.of(ipv6,
+                    IPv6Address.ofCidrMaskLength(cidrMaskLength));
         }
     }
 
+    @Override
+    public boolean contains(IPAddress<?> ip) {
+        Preconditions.checkNotNull(ip, "ip must not be null");
 
+        if(ip.getIpVersion() == IPVersion.IPv6) {
+            IPv6Address ipv6 = (IPv6Address) ip;
+            return this.matches(ipv6);
+        }
+
+        return false;
+    }
 }
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java
index 35ef846..ddf4faa 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java
@@ -123,15 +123,100 @@
     }
 
     @Override
+    public U128 add(U128 other) {
+        long newRaw2 = this.raw2 + other.raw2;
+        long newRaw1 = this.raw1 + other.raw1;
+        if(UnsignedLongs.compare(newRaw2, this.raw2) < 0) {
+            // raw2 overflow
+            newRaw1+=1;
+        }
+        return U128.of(newRaw1, newRaw2);
+    }
+
+    @Override
+    public U128 subtract(U128 other) {
+        long newRaw2 = this.raw2 - other.raw2;
+        long newRaw1 = this.raw1 - other.raw1;
+        if(UnsignedLongs.compare(this.raw2, other.raw2) < 0) {
+            newRaw1 -= 1;
+        }
+        return U128.of(newRaw1, newRaw2);
+    }
+    @Override
     public int prefixBits(int numBits) {
         return HashValueUtils.prefixBits(this.raw1, numBits);
     }
 
     @Override
-    public U128 combineWithValue(U128 value, int keyBits) {
-        return U128.of(
-                HashValueUtils.combineWithValue(this.raw1, value.raw1, Math.min(64, keyBits)),
-                HashValueUtils.combineWithValue(this.raw2, value.raw2, Math.max(0,keyBits-64))
-        );
+    public HashValue.Builder<U128> builder() {
+        return new U128Builder(raw1, raw2);
     }
+
+    static class U128Builder implements HashValue.Builder<U128> {
+        private long raw1, raw2;
+
+        public U128Builder(long raw1, long raw2) {
+            this.raw1 = raw1;
+            this.raw2 = raw2;
+        }
+
+        @Override
+        public Builder<U128> add(U128 other) {
+            raw2 += other.raw2;
+            raw1 += other.raw1;
+            if(UnsignedLongs.compare(raw2, other.raw2) < 0) {
+                // raw2 overflow
+                raw1+=1;
+            }
+            return this;
+        }
+
+        @Override
+        public Builder<U128> subtract(
+                U128 other) {
+            if(UnsignedLongs.compare(this.raw2, other.raw2) >= 0) {
+                raw2 -= other.raw2;
+                raw1 -= other.raw1;
+            } else {
+                // raw2 overflow
+                raw2 -= other.raw2;
+                raw1 = this.raw1 - other.raw1 - 1;
+            }
+            return this;
+        }
+
+        @Override
+        public Builder<U128> invert() {
+            raw1 = ~raw1;
+            raw2 = ~raw2;
+            return this;
+        }
+
+        @Override
+        public Builder<U128> or(U128 other) {
+            raw1 |= other.raw1;
+            raw2 |= other.raw2;
+            return this;
+        }
+
+        @Override
+        public Builder<U128> and(U128 other) {
+            raw1 &= other.raw1;
+            raw2 &= other.raw2;
+            return this;
+        }
+
+        @Override
+        public Builder<U128> xor(U128 other) {
+            raw1 ^= other.raw1;
+            raw2 ^= other.raw2;
+            return this;
+        }
+
+        @Override
+        public U128 build() {
+            return U128.of(raw1, raw2);
+        }
+    }
+
 }
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java
index 1353b42..f15544f 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java
@@ -151,6 +151,16 @@
         return U64.of(raw ^ other.raw);
     }
 
+    @Override
+    public U64 add(U64 other) {
+        return U64.of(this.raw + other.raw);
+    }
+
+    @Override
+    public U64 subtract(U64 other) {
+        return U64.of(this.raw - other.raw);
+    }
+
     /** return the "numBits" highest-order bits of the hash.
      *  @param numBits number of higest-order bits to return [0-32].
      *  @return a numberic value of the 0-32 highest-order bits.
@@ -160,11 +170,6 @@
         return HashValueUtils.prefixBits(raw, numBits);
     }
 
-    @Override
-    public U64 combineWithValue(U64 value, int keyBits) {
-        return U64.of(HashValueUtils.combineWithValue(this.raw, value.raw, keyBits));
-    }
-
     public final static Reader READER = new Reader();
 
     private static class Reader implements OFMessageReader<U64> {
@@ -174,5 +179,59 @@
         }
     }
 
+    @Override
+    public HashValue.Builder<U64> builder() {
+        return new U64Builder(raw);
+    }
+
+    static class U64Builder implements Builder<U64> {
+        long raw;
+
+        public U64Builder(long raw) {
+            this.raw = raw;
+        }
+
+        @Override
+        public Builder<U64> add(U64 other) {
+            raw += other.raw;
+            return this;
+        }
+
+        @Override
+        public Builder<U64> subtract(
+                U64 other) {
+            raw -= other.raw;
+            return this;
+        }
+
+        @Override
+        public Builder<U64> invert() {
+            raw = ~raw;
+            return this;
+        }
+
+        @Override
+        public Builder<U64> or(U64 other) {
+            raw |= other.raw;
+            return this;
+        }
+
+        @Override
+        public Builder<U64> and(U64 other) {
+            raw &= other.raw;
+            return this;
+        }
+
+        @Override
+        public Builder<U64> xor(U64 other) {
+            raw ^= other.raw;
+            return this;
+        }
+
+        @Override
+        public U64 build() {
+            return U64.of(raw);
+        }
+    }
 
 }