Work toward common IP address classes.

Ported the following IP address classes from the older codebase:
Ip4Address, Ip6Address, Ip4Prefix, Ip6Prefix (and the corresponding
unit tests).
NOTE: Those classes are not ready to be used yet.

Change-Id: I234875abbc9df8daa2f8ae28706af591dd2c5f2d
diff --git a/utils/misc/src/main/java/org/onlab/packet/Ip4Address.java b/utils/misc/src/main/java/org/onlab/packet/Ip4Address.java
new file mode 100644
index 0000000..1571cf6
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/Ip4Address.java
@@ -0,0 +1,202 @@
+package org.onlab.packet;
+
+import java.nio.ByteBuffer;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * The class representing an IPv4 address.
+ * This class is immutable.
+ */
+public final class Ip4Address implements Comparable<Ip4Address> {
+    private final int value;
+
+    /** The length of the address in bytes (octets). */
+    public static final int BYTE_LENGTH = 4;
+
+    /** The length of the address in bits. */
+    public static final int BIT_LENGTH = BYTE_LENGTH * Byte.SIZE;
+
+    /**
+     * Default constructor.
+     */
+    public Ip4Address() {
+        this.value = 0;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from
+     */
+    public Ip4Address(Ip4Address other) {
+        this.value = other.value;
+    }
+
+    /**
+     * Constructor from an integer value.
+     *
+     * @param value the value to use
+     */
+    public Ip4Address(int value) {
+        this.value = value;
+    }
+
+    /**
+     * Constructor from a byte array with the IPv4 address stored in network
+     * byte order (i.e., the most significant byte first).
+     *
+     * @param value the value to use
+     */
+    public Ip4Address(byte[] value) {
+        this(value, 0);
+    }
+
+    /**
+     * Constructor from a byte array with the IPv4 address stored in network
+     * byte order (i.e., the most significant byte first), and a given offset
+     * from the beginning of the byte array.
+     *
+     * @param value the value to use
+     * @param offset the offset in bytes from the beginning of the byte array
+     */
+    public Ip4Address(byte[] value, int offset) {
+        checkNotNull(value);
+
+        // Verify the arguments
+        if ((offset < 0) || (offset + BYTE_LENGTH > value.length)) {
+            String msg;
+            if (value.length < BYTE_LENGTH) {
+                msg = "Invalid IPv4 address array: array length: " +
+                    value.length + ". Must be at least " + BYTE_LENGTH;
+            } else {
+                msg = "Invalid IPv4 address array: array offset: " +
+                    offset + ". Must be in the interval [0, " +
+                    (value.length - BYTE_LENGTH) + "]";
+            }
+            throw new IllegalArgumentException(msg);
+        }
+
+        // Read the address
+        ByteBuffer bb = ByteBuffer.wrap(value);
+        this.value = bb.getInt(offset);
+    }
+
+    /**
+     * Constructs an IPv4 address from a string representation of the address.
+     *<p>
+     * Example: "1.2.3.4"
+     *
+     * @param value the value to use
+     */
+    public Ip4Address(String value) {
+        checkNotNull(value);
+
+        String[] splits = value.split("\\.");
+        if (splits.length != 4) {
+            final String msg = "Invalid IPv4 address string: " + value;
+            throw new IllegalArgumentException(msg);
+        }
+
+        int result = 0;
+        for (int i = 0; i < BYTE_LENGTH; i++) {
+            result |= Integer.parseInt(splits[i]) <<
+                ((BYTE_LENGTH - (i + 1)) * Byte.SIZE);
+        }
+        this.value = result;
+    }
+
+    /**
+     * Gets the IPv4 address as a byte array.
+     *
+     * @return a byte array with the IPv4 address stored in network byte order
+     * (i.e., the most significant byte first).
+     */
+    public byte[] toOctets() {
+        return ByteBuffer.allocate(BYTE_LENGTH).putInt(value).array();
+    }
+
+    /**
+     * Creates an IPv4 network mask prefix.
+     *
+     * @param prefixLen the length of the mask prefix. Must be in the interval
+     * [0, 32].
+     * @return a new IPv4 address that contains a mask prefix of the
+     * specified length
+     */
+    public static Ip4Address makeMaskPrefix(int prefixLen) {
+        // Verify the prefix length
+        if ((prefixLen < 0) || (prefixLen > Ip4Address.BIT_LENGTH)) {
+            final String msg = "Invalid IPv4 prefix length: " + prefixLen +
+                ". Must be in the interval [0, 32].";
+            throw new IllegalArgumentException(msg);
+        }
+
+        long v =
+            (0xffffffffL << (Ip4Address.BIT_LENGTH - prefixLen)) & 0xffffffffL;
+        return new Ip4Address((int) v);
+    }
+
+    /**
+     * Creates an IPv4 address by masking it with a network mask of given
+     * mask length.
+     *
+     * @param addr the address to mask
+     * @param prefixLen the length of the mask prefix. Must be in the interval
+     * [0, 32].
+     * @return a new IPv4 address that is masked with a mask prefix of the
+     * specified length
+     */
+    public static Ip4Address makeMaskedAddress(final Ip4Address addr,
+                                               int prefixLen) {
+        Ip4Address mask = Ip4Address.makeMaskPrefix(prefixLen);
+        long v = addr.value & mask.value;
+
+        return new Ip4Address((int) v);
+    }
+
+    /**
+     * Gets the value of the IPv4 address.
+     *
+     * @return the value of the IPv4 address
+     */
+    public int getValue() {
+        return value;
+    }
+
+    /**
+     * Converts the IPv4 value to a '.' separated string.
+     *
+     * @return the IPv4 value as a '.' separated string
+     */
+    @Override
+    public String toString() {
+        return ((this.value >> 24) & 0xff) + "." +
+                ((this.value >> 16) & 0xff) + "." +
+                ((this.value >> 8) & 0xff) + "." +
+                (this.value & 0xff);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof Ip4Address)) {
+            return false;
+        }
+        Ip4Address other = (Ip4Address) o;
+        if (this.value != other.value) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.value;
+    }
+
+    @Override
+    public int compareTo(Ip4Address o) {
+        Long lv = ((long) this.value) & 0xffffffffL;
+        Long rv = ((long) o.value) & 0xffffffffL;
+        return lv.compareTo(rv);
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/Ip4Prefix.java b/utils/misc/src/main/java/org/onlab/packet/Ip4Prefix.java
new file mode 100644
index 0000000..4d0c755
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/Ip4Prefix.java
@@ -0,0 +1,123 @@
+package org.onlab.packet;
+
+import java.util.Objects;
+
+/**
+ * The class representing an IPv4 network address.
+ * This class is immutable.
+ */
+public final class Ip4Prefix {
+    private final Ip4Address address;           // The IPv4 address
+    private final short prefixLen;              // The prefix length
+
+    /**
+     * Default constructor.
+     */
+    public Ip4Prefix() {
+        this.address = new Ip4Address();
+        this.prefixLen = 0;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from
+     */
+    public Ip4Prefix(Ip4Prefix other) {
+        this.address = new Ip4Address(other.address);
+        this.prefixLen = other.prefixLen;
+    }
+
+    /**
+     * Constructor for a given address and prefix length.
+     *
+     * @param address   the address to use
+     * @param prefixLen the prefix length to use
+     */
+    public Ip4Prefix(Ip4Address address, short prefixLen) {
+        this.address = Ip4Address.makeMaskedAddress(address, prefixLen);
+        this.prefixLen = prefixLen;
+    }
+
+    /**
+     * Constructs an IPv4 prefix from a string representation of the
+     * prefix.
+     *<p>
+     * Example: "1.2.0.0/16"
+     *
+     * @param value the value to use
+     */
+    public Ip4Prefix(String value) {
+        String[] splits = value.split("/");
+        if (splits.length != 2) {
+            throw new IllegalArgumentException("Specified IPv4 prefix must contain an IPv4 " +
+                    "address and a prefix length separated by '/'");
+        }
+        this.prefixLen = Short.decode(splits[1]);
+        this.address = Ip4Address.makeMaskedAddress(new Ip4Address(splits[0]),
+                this.prefixLen);
+    }
+
+    /**
+     * Gets the address value of the IPv4 prefix.
+     *
+     * @return the address value of the IPv4 prefix
+     */
+    public Ip4Address getAddress() {
+        return address;
+    }
+
+    /**
+     * Gets the prefix length value of the IPv4 prefix.
+     *
+     * @return the prefix length value of the IPv4 prefix
+     */
+    public short getPrefixLen() {
+        return prefixLen;
+    }
+
+    /**
+     * Converts the IPv4 prefix value to an "address/prefixLen" string.
+     *
+     * @return the IPv4 prefix value as an "address/prefixLen" string
+     */
+    @Override
+    public String toString() {
+        return this.address.toString() + "/" + this.prefixLen;
+    }
+
+    /**
+     * Compares the value of two Ip4Prefix objects.
+     * <p/>
+     * Note the value of the IPv4 address is compared directly between the
+     * objects, and must match exactly for the objects to be considered equal.
+     * This may result in objects which represent the same IP prefix being
+     * classified as unequal, because the unsignificant bits of the address
+     * field don't match (the bits to the right of the prefix length).
+     * <p/>
+     * TODO Change this behavior so that objects that represent the same prefix
+     * are classified as equal according to this equals method.
+     *
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!(other instanceof Ip4Prefix)) {
+            return false;
+        }
+
+        Ip4Prefix otherIp4Prefix = (Ip4Prefix) other;
+
+        return Objects.equals(this.address, otherIp4Prefix.address)
+                && this.prefixLen == otherIp4Prefix.prefixLen;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(address, prefixLen);
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/Ip6Address.java b/utils/misc/src/main/java/org/onlab/packet/Ip6Address.java
new file mode 100644
index 0000000..57e893f
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/Ip6Address.java
@@ -0,0 +1,260 @@
+package org.onlab.packet;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+import com.google.common.net.InetAddresses;
+import com.google.common.primitives.UnsignedLongs;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * The class representing an IPv6 address.
+ * This class is immutable.
+ */
+public final class Ip6Address implements Comparable<Ip6Address> {
+    private final long valueHigh;    // The higher (more significant) 64 bits
+    private final long valueLow;     // The lower (less significant) 64 bits
+
+    /** The length of the address in bytes (octets). */
+    public static final int BYTE_LENGTH = 16;
+
+    /** The length of the address in bits. */
+    public static final int BIT_LENGTH = BYTE_LENGTH * Byte.SIZE;
+
+    /**
+     * Default constructor.
+     */
+    public Ip6Address() {
+        this.valueHigh = 0;
+        this.valueLow = 0;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from
+     */
+    public Ip6Address(Ip6Address other) {
+        this.valueHigh = other.valueHigh;
+        this.valueLow = other.valueLow;
+    }
+
+    /**
+     * Constructor from integer values.
+     *
+     * @param valueHigh the higher (more significant) 64 bits of the address
+     * @param valueLow  the lower (less significant) 64 bits of the address
+     */
+    public Ip6Address(long valueHigh, long valueLow) {
+        this.valueHigh = valueHigh;
+        this.valueLow = valueLow;
+    }
+
+    /**
+     * Constructor from a byte array with the IPv6 address stored in network
+     * byte order (i.e., the most significant byte first).
+     *
+     * @param value the value to use
+     */
+    public Ip6Address(byte[] value) {
+        this(value, 0);
+    }
+
+    /**
+     * Constructor from a byte array with the IPv6 address stored in network
+     * byte order (i.e., the most significant byte first), and a given offset
+     * from the beginning of the byte array.
+     *
+     * @param value the value to use
+     * @param offset the offset in bytes from the beginning of the byte array
+     */
+    public Ip6Address(byte[] value, int offset) {
+        checkNotNull(value);
+
+        // Verify the arguments
+        if ((offset < 0) || (offset + BYTE_LENGTH > value.length)) {
+            String msg;
+            if (value.length < BYTE_LENGTH) {
+                msg = "Invalid IPv6 address array: array length: " +
+                    value.length + ". Must be at least " + BYTE_LENGTH;
+            } else {
+                msg = "Invalid IPv6 address array: array offset: " +
+                    offset + ". Must be in the interval [0, " +
+                    (value.length - BYTE_LENGTH) + "]";
+            }
+            throw new IllegalArgumentException(msg);
+        }
+
+        // Read the address
+        ByteBuffer bb = ByteBuffer.wrap(value);
+        bb.position(offset);
+        this.valueHigh = bb.getLong();
+        this.valueLow = bb.getLong();
+    }
+
+    /**
+     * Constructs an IPv6 address from a string representation of the address.
+     *<p>
+     * Example: "1111:2222::8888"
+     *
+     * @param value the value to use
+     */
+    public Ip6Address(String value) {
+        checkNotNull(value);
+
+        if (value.isEmpty()) {
+            final String msg = "Specified IPv6 cannot be an empty string";
+            throw new IllegalArgumentException(msg);
+        }
+        InetAddress addr = null;
+        try {
+            addr = InetAddresses.forString(value);
+        } catch (IllegalArgumentException e) {
+            final String msg = "Invalid IPv6 address string: " + value;
+            throw new IllegalArgumentException(msg);
+        }
+        byte[] bytes = addr.getAddress();
+        ByteBuffer bb = ByteBuffer.wrap(bytes);
+        this.valueHigh = bb.getLong();
+        this.valueLow = bb.getLong();
+    }
+
+    /**
+     * Gets the IPv6 address as a byte array.
+     *
+     * @return a byte array with the IPv6 address stored in network byte order
+     * (i.e., the most significant byte first).
+     */
+    public byte[] toOctets() {
+        return ByteBuffer.allocate(BYTE_LENGTH)
+            .putLong(valueHigh).putLong(valueLow).array();
+    }
+
+    /**
+     * Creates an IPv6 network mask prefix.
+     *
+     * @param prefixLen the length of the mask prefix. Must be in the interval
+     * [0, 128].
+     * @return a new IPv6 address that contains a mask prefix of the
+     * specified length
+     */
+    public static Ip6Address makeMaskPrefix(int prefixLen) {
+        long vh, vl;
+
+        // Verify the prefix length
+        if ((prefixLen < 0) || (prefixLen > Ip6Address.BIT_LENGTH)) {
+            final String msg = "Invalid IPv6 prefix length: " + prefixLen +
+                ". Must be in the interval [0, 128].";
+            throw new IllegalArgumentException(msg);
+        }
+
+        if (prefixLen == 0) {
+            //
+            // NOTE: Apparently, the result of "<< 64" shifting to the left
+            // results in all 1s instead of all 0s, hence we handle it as
+            // a special case.
+            //
+            vh = 0;
+            vl = 0;
+        } else if (prefixLen <= 64) {
+            vh = (0xffffffffffffffffL << (64 - prefixLen)) & 0xffffffffffffffffL;
+            vl = 0;
+        } else {
+            vh = -1L;           // All 1s
+            vl = (0xffffffffffffffffL << (128 - prefixLen)) & 0xffffffffffffffffL;
+        }
+        return new Ip6Address(vh, vl);
+    }
+
+    /**
+     * Creates an IPv6 address by masking it with a network mask of given
+     * mask length.
+     *
+     * @param addr the address to mask
+     * @param prefixLen the length of the mask prefix. Must be in the interval
+     * [0, 128].
+     * @return a new IPv6 address that is masked with a mask prefix of the
+     * specified length
+     */
+    public static Ip6Address makeMaskedAddress(final Ip6Address addr,
+                                               int prefixLen) {
+        Ip6Address mask = Ip6Address.makeMaskPrefix(prefixLen);
+        long vh = addr.valueHigh & mask.valueHigh;
+        long vl = addr.valueLow & mask.valueLow;
+
+        return new Ip6Address(vh, vl);
+    }
+
+    /**
+     * Gets the value of the higher (more significant) 64 bits of the address.
+     *
+     * @return the value of the higher (more significant) 64 bits of the
+     * address
+     */
+    public long getValueHigh() {
+        return valueHigh;
+    }
+
+    /**
+     * Gets the value of the lower (less significant) 64 bits of the address.
+     *
+     * @return the value of the lower (less significant) 64 bits of the
+     * address
+     */
+    public long getValueLow() {
+        return valueLow;
+    }
+
+    /**
+     * Converts the IPv6 value to a ':' separated string.
+     *
+     * @return the IPv6 value as a ':' separated string
+     */
+    @Override
+    public String toString() {
+        ByteBuffer bb = ByteBuffer.allocate(Ip6Address.BYTE_LENGTH);
+        bb.putLong(valueHigh);
+        bb.putLong(valueLow);
+        InetAddress inetAddr = null;
+        try {
+            inetAddr = InetAddress.getByAddress(bb.array());
+        } catch (UnknownHostException e) {
+            // Should never happen
+            checkState(false, "Internal error: Ip6Address.toString()");
+            return "::";
+        }
+        return InetAddresses.toAddrString(inetAddr);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof Ip6Address)) {
+            return false;
+        }
+        Ip6Address other = (Ip6Address) o;
+        return this.valueHigh == other.valueHigh
+                && this.valueLow == other.valueLow;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(valueHigh, valueLow);
+    }
+
+    @Override
+    public int compareTo(Ip6Address o) {
+        // Compare the high-order 64-bit value
+        if (this.valueHigh != o.valueHigh) {
+            return UnsignedLongs.compare(this.valueHigh, o.valueHigh);
+        }
+        // Compare the low-order 64-bit value
+        if (this.valueLow != o.valueLow) {
+            return UnsignedLongs.compare(this.valueLow, o.valueLow);
+        }
+        return 0;
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/Ip6Prefix.java b/utils/misc/src/main/java/org/onlab/packet/Ip6Prefix.java
new file mode 100644
index 0000000..d38f505
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/Ip6Prefix.java
@@ -0,0 +1,123 @@
+package org.onlab.packet;
+
+import java.util.Objects;
+
+/**
+ * The class representing an IPv6 network address.
+ * This class is immutable.
+ */
+public final class Ip6Prefix {
+    private final Ip6Address address;           // The IPv6 address
+    private final short prefixLen;              // The prefix length
+
+    /**
+     * Default constructor.
+     */
+    public Ip6Prefix() {
+        this.address = new Ip6Address();
+        this.prefixLen = 0;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from
+     */
+    public Ip6Prefix(Ip6Prefix other) {
+        this.address = new Ip6Address(other.address);
+        this.prefixLen = other.prefixLen;
+    }
+
+    /**
+     * Constructor for a given address and prefix length.
+     *
+     * @param address   the address to use
+     * @param prefixLen the prefix length to use
+     */
+    public Ip6Prefix(Ip6Address address, short prefixLen) {
+        this.address = Ip6Address.makeMaskedAddress(address, prefixLen);
+        this.prefixLen = prefixLen;
+    }
+
+    /**
+     * Constructs an IPv6 prefix from a string representation of the
+     * prefix.
+     *<p>
+     * Example: "1111:2222::/32"
+     *
+     * @param value the value to use
+     */
+    public Ip6Prefix(String value) {
+        String[] splits = value.split("/");
+        if (splits.length != 2) {
+            throw new IllegalArgumentException("Specified IPv6 prefix must contain an IPv6 " +
+                    "address and a prefix length separated by '/'");
+        }
+        this.prefixLen = Short.decode(splits[1]);
+        this.address = Ip6Address.makeMaskedAddress(new Ip6Address(splits[0]),
+                this.prefixLen);
+    }
+
+    /**
+     * Gets the address value of the IPv6 prefix.
+     *
+     * @return the address value of the IPv6 prefix
+     */
+    public Ip6Address getAddress() {
+        return address;
+    }
+
+    /**
+     * Gets the prefix length value of the IPv6 prefix.
+     *
+     * @return the prefix length value of the IPv6 prefix
+     */
+    public short getPrefixLen() {
+        return prefixLen;
+    }
+
+    /**
+     * Converts the IPv6 prefix value to an "address/prefixLen" string.
+     *
+     * @return the IPv6 prefix value as an "address/prefixLen" string
+     */
+    @Override
+    public String toString() {
+        return this.address.toString() + "/" + this.prefixLen;
+    }
+
+    /**
+     * Compares the value of two Ip6Prefix objects.
+     * <p/>
+     * Note the value of the IPv6 address is compared directly between the
+     * objects, and must match exactly for the objects to be considered equal.
+     * This may result in objects which represent the same IP prefix being
+     * classified as unequal, because the unsignificant bits of the address
+     * field don't match (the bits to the right of the prefix length).
+     * <p/>
+     * TODO Change this behavior so that objects that represent the same prefix
+     * are classified as equal according to this equals method.
+     *
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!(other instanceof Ip6Prefix)) {
+            return false;
+        }
+
+        Ip6Prefix otherIp6Prefix = (Ip6Prefix) other;
+
+        return Objects.equals(this.address, otherIp6Prefix.address)
+                && this.prefixLen == otherIp6Prefix.prefixLen;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(address, prefixLen);
+    }
+}
diff --git a/utils/misc/src/test/java/org/onlab/packet/Ip4AddressTest.java b/utils/misc/src/test/java/org/onlab/packet/Ip4AddressTest.java
new file mode 100644
index 0000000..6680af4
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/Ip4AddressTest.java
@@ -0,0 +1,330 @@
+package org.onlab.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Tests for class {@link Ip4Address}.
+ */
+public class Ip4AddressTest {
+    /**
+     * Tests the immutability of {@link Ip4Address}.
+     */
+    @Test
+    public void testImmutable() {
+        assertThatClassIsImmutable(Ip4Address.class);
+    }
+
+    /**
+     * Tests the length of the address in bytes (octets).
+     */
+    @Test
+    public void testAddrBytelen() {
+        assertThat(Ip4Address.BYTE_LENGTH, is(4));
+    }
+
+    /**
+     * Tests the length of the address in bits.
+     */
+    @Test
+    public void testAddrBitlen() {
+        assertThat(Ip4Address.BIT_LENGTH, is(32));
+    }
+
+    /**
+     * Tests default class constructor.
+     */
+    @Test
+    public void testDefaultConstructor() {
+        Ip4Address ip4Address = new Ip4Address();
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+    }
+
+    /**
+     * Tests valid class copy constructor.
+     */
+    @Test
+    public void testCopyConstructor() {
+        Ip4Address fromAddr = new Ip4Address("1.2.3.4");
+        Ip4Address ip4Address = new Ip4Address(fromAddr);
+        assertThat(ip4Address.toString(), is("1.2.3.4"));
+
+        fromAddr = new Ip4Address("0.0.0.0");
+        ip4Address = new Ip4Address(fromAddr);
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+
+        fromAddr = new Ip4Address("255.255.255.255");
+        ip4Address = new Ip4Address(fromAddr);
+        assertThat(ip4Address.toString(), is("255.255.255.255"));
+    }
+
+    /**
+     * Tests invalid class copy constructor for a null object to copy from.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullObject() {
+        Ip4Address fromAddr = null;
+        Ip4Address ip4Address = new Ip4Address(fromAddr);
+    }
+
+    /**
+     * Tests valid class constructor for an integer value.
+     */
+    @Test
+    public void testConstructorForInteger() {
+        Ip4Address ip4Address = new Ip4Address(0x01020304);
+        assertThat(ip4Address.toString(), is("1.2.3.4"));
+
+        ip4Address = new Ip4Address(0);
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+
+        ip4Address = new Ip4Address(0xffffffff);
+        assertThat(ip4Address.toString(), is("255.255.255.255"));
+    }
+
+    /**
+     * Tests valid class constructor for an array value.
+     */
+    @Test
+    public void testConstructorForArray() {
+        final byte[] value1 = new byte[] {1, 2, 3, 4};
+        Ip4Address ip4Address = new Ip4Address(value1);
+        assertThat(ip4Address.toString(), is("1.2.3.4"));
+
+        final byte[] value2 = new byte[] {0, 0, 0, 0};
+        ip4Address = new Ip4Address(value2);
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+
+        final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff};
+        ip4Address = new Ip4Address(value3);
+        assertThat(ip4Address.toString(), is("255.255.255.255"));
+    }
+
+    /**
+     * Tests valid class constructor for an array value and an offset.
+     */
+    @Test
+    public void testConstructorForArrayAndOffset() {
+        final byte[] value1 = new byte[] {11, 22, 33,   // Preamble
+                                          1, 2, 3, 4,
+                                          44, 55};      // Extra bytes
+        Ip4Address ip4Address = new Ip4Address(value1, 3);
+        assertThat(ip4Address.toString(), is("1.2.3.4"));
+
+        final byte[] value2 = new byte[] {11, 22,       // Preamble
+                                          0, 0, 0, 0,
+                                          33};          // Extra bytes
+        ip4Address = new Ip4Address(value2, 2);
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+
+        final byte[] value3 = new byte[] {11, 22,       // Preamble
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          33};          // Extra bytes
+        ip4Address = new Ip4Address(value3, 2);
+        assertThat(ip4Address.toString(), is("255.255.255.255"));
+    }
+
+    /**
+     * Tests invalid class constructor for a null array.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullArray() {
+        final byte[] fromArray = null;
+        Ip4Address ip4Address = new Ip4Address(fromArray);
+    }
+
+    /**
+     * Tests invalid class constructor for an array that is too short.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructorShortArray() {
+        final byte[] fromArray = new byte[] {1, 2, 3};
+        Ip4Address ip4Address = new Ip4Address(fromArray);
+    }
+
+    /**
+     * Tests invalid class constructor for an array and an invalid offset.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructorArrayInvalidOffset() {
+        final byte[] value1 = new byte[] {11, 22, 33,   // Preamble
+                                          1, 2, 3, 4,
+                                          44, 55};      // Extra bytes
+        Ip4Address ip4Address = new Ip4Address(value1, 6);
+    }
+
+    /**
+     * Tests valid class constructor for a string.
+     */
+    @Test
+    public void testConstructorForString() {
+        Ip4Address ip4Address = new Ip4Address("1.2.3.4");
+        assertThat(ip4Address.toString(), is("1.2.3.4"));
+
+        ip4Address = new Ip4Address("0.0.0.0");
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+
+        ip4Address = new Ip4Address("255.255.255.255");
+        assertThat(ip4Address.toString(), is("255.255.255.255"));
+    }
+
+    /**
+     * Tests invalid class constructor for a null string.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullString() {
+        String fromString = null;
+        Ip4Address ip4Address = new Ip4Address(fromString);
+    }
+
+    /**
+     * Tests invalid class constructor for an empty string.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructors() {
+        // Check constructor for invalid ID: empty string
+        Ip4Address ip4Address = new Ip4Address("");
+    }
+
+    /**
+     * Tests returning the address as a byte array.
+     */
+    @Test
+    public void testAddressToOctets() {
+        final byte[] value1 = new byte[] {1, 2, 3, 4};
+        Ip4Address ip4Address = new Ip4Address("1.2.3.4");
+        assertThat(ip4Address.toOctets(), is(value1));
+
+        final byte[] value2 = new byte[] {0, 0, 0, 0};
+        ip4Address = new Ip4Address("0.0.0.0");
+        assertThat(ip4Address.toOctets(), is(value2));
+
+        final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff};
+        ip4Address = new Ip4Address("255.255.255.255");
+        assertThat(ip4Address.toOctets(), is(value3));
+    }
+
+    /**
+     * Tests making a mask prefix for a given prefix length.
+     */
+    @Test
+    public void testMakeMaskPrefix() {
+        Ip4Address ip4Address = Ip4Address.makeMaskPrefix(25);
+        assertThat(ip4Address.toString(), is("255.255.255.128"));
+
+        ip4Address = Ip4Address.makeMaskPrefix(0);
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+
+        ip4Address = Ip4Address.makeMaskPrefix(32);
+        assertThat(ip4Address.toString(), is("255.255.255.255"));
+    }
+
+    /**
+     * Tests making of a masked address.
+     */
+    @Test
+    public void testMakeMaskedAddress() {
+        Ip4Address ip4Address = new Ip4Address("1.2.3.5");
+        Ip4Address ip4AddressMasked =
+            Ip4Address.makeMaskedAddress(ip4Address, 24);
+        assertThat(ip4AddressMasked.toString(), is("1.2.3.0"));
+
+        ip4AddressMasked = Ip4Address.makeMaskedAddress(ip4Address, 0);
+        assertThat(ip4AddressMasked.toString(), is("0.0.0.0"));
+
+        ip4AddressMasked = Ip4Address.makeMaskedAddress(ip4Address, 32);
+        assertThat(ip4AddressMasked.toString(), is("1.2.3.5"));
+    }
+
+    /**
+     * Tests getting the value of an address.
+     */
+    @Test
+    public void testGetValue() {
+        Ip4Address ip4Address = new Ip4Address("1.2.3.4");
+        assertThat(ip4Address.getValue(), is(0x01020304));
+
+        ip4Address = new Ip4Address("0.0.0.0");
+        assertThat(ip4Address.getValue(), is(0));
+
+        ip4Address = new Ip4Address("255.255.255.255");
+        assertThat(ip4Address.getValue(), is(-1));
+    }
+
+    /**
+     * Tests equality of {@link Ip4Address}.
+     */
+    @Test
+    public void testEquality() {
+        Ip4Address addr1 = new Ip4Address("1.2.3.4");
+        Ip4Address addr2 = new Ip4Address("1.2.3.4");
+        assertThat(addr1, is(addr2));
+
+        addr1 = new Ip4Address("0.0.0.0");
+        addr2 = new Ip4Address("0.0.0.0");
+        assertThat(addr1, is(addr2));
+
+        addr1 = new Ip4Address("255.255.255.255");
+        addr2 = new Ip4Address("255.255.255.255");
+        assertThat(addr1, is(addr2));
+    }
+
+    /**
+     * Tests non-equality of {@link Ip4Address}.
+     */
+    @Test
+    public void testNonEquality() {
+        Ip4Address addr1 = new Ip4Address("1.2.3.4");
+        Ip4Address addr2 = new Ip4Address("1.2.3.5");
+        Ip4Address addr3 = new Ip4Address("0.0.0.0");
+        Ip4Address addr4 = new Ip4Address("255.255.255.255");
+        assertThat(addr1, is(not(addr2)));
+        assertThat(addr3, is(not(addr2)));
+        assertThat(addr4, is(not(addr2)));
+    }
+
+    /**
+     * Tests comparison of {@link Ip4Address}.
+     */
+    @Test
+    public void testComparison() {
+        Ip4Address addr1 = new Ip4Address("1.2.3.4");
+        Ip4Address addr2 = new Ip4Address("1.2.3.4");
+        Ip4Address addr3 = new Ip4Address("1.2.3.3");
+        Ip4Address addr4 = new Ip4Address("1.2.3.5");
+        assertTrue(addr1.compareTo(addr2) == 0);
+        assertTrue(addr1.compareTo(addr3) > 0);
+        assertTrue(addr1.compareTo(addr4) < 0);
+
+        addr1 = new Ip4Address("255.2.3.4");
+        addr2 = new Ip4Address("255.2.3.4");
+        addr3 = new Ip4Address("255.2.3.3");
+        addr4 = new Ip4Address("255.2.3.5");
+        assertTrue(addr1.compareTo(addr2) == 0);
+        assertTrue(addr1.compareTo(addr3) > 0);
+        assertTrue(addr1.compareTo(addr4) < 0);
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        Ip4Address ip4Address = new Ip4Address("1.2.3.4");
+        assertThat(ip4Address.toString(), is("1.2.3.4"));
+
+        ip4Address = new Ip4Address("0.0.0.0");
+        assertThat(ip4Address.toString(), is("0.0.0.0"));
+
+        ip4Address = new Ip4Address("255.255.255.255");
+        assertThat(ip4Address.toString(), is("255.255.255.255"));
+    }
+}
diff --git a/utils/misc/src/test/java/org/onlab/packet/Ip4PrefixTest.java b/utils/misc/src/test/java/org/onlab/packet/Ip4PrefixTest.java
new file mode 100644
index 0000000..3e502d3
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/Ip4PrefixTest.java
@@ -0,0 +1,195 @@
+package org.onlab.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Tests for class {@link Ip4Prefix}.
+ */
+public class Ip4PrefixTest {
+    /**
+     * Tests the immutability of {@link Ip4Prefix}.
+     */
+    @Test
+    public void testImmutable() {
+        assertThatClassIsImmutable(Ip4Prefix.class);
+    }
+
+    /**
+     * Tests default class constructor.
+     */
+    @Test
+    public void testDefaultConstructor() {
+        Ip4Prefix ip4prefix = new Ip4Prefix();
+        assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
+    }
+
+    /**
+     * Tests valid class copy constructor.
+     */
+    @Test
+    public void testCopyConstructor() {
+        Ip4Prefix fromAddr = new Ip4Prefix("1.2.3.0/24");
+        Ip4Prefix ip4prefix = new Ip4Prefix(fromAddr);
+        assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
+
+        fromAddr = new Ip4Prefix("0.0.0.0/0");
+        ip4prefix = new Ip4Prefix(fromAddr);
+        assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
+
+        fromAddr = new Ip4Prefix("255.255.255.255/32");
+        ip4prefix = new Ip4Prefix(fromAddr);
+        assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
+    }
+
+    /**
+     * Tests invalid class copy constructor for a null object to copy from.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullObject() {
+        Ip4Prefix fromAddr = null;
+        Ip4Prefix ip4prefix = new Ip4Prefix(fromAddr);
+    }
+
+    /**
+     * Tests valid class constructor for an address and prefix length.
+     */
+    @Test
+    public void testConstructorForAddressAndPrefixLength() {
+        Ip4Prefix ip4prefix =
+            new Ip4Prefix(new Ip4Address("1.2.3.0"), (short) 24);
+        assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
+
+        ip4prefix = new Ip4Prefix(new Ip4Address("1.2.3.4"), (short) 24);
+        assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
+
+        ip4prefix = new Ip4Prefix(new Ip4Address("1.2.3.5"), (short) 32);
+        assertThat(ip4prefix.toString(), is("1.2.3.5/32"));
+
+        ip4prefix = new Ip4Prefix(new Ip4Address("0.0.0.0"), (short) 0);
+        assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
+
+        ip4prefix =
+            new Ip4Prefix(new Ip4Address("255.255.255.255"), (short) 32);
+        assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
+    }
+
+    /**
+     * Tests valid class constructor for a string.
+     */
+    @Test
+    public void testConstructorForString() {
+        Ip4Prefix ip4prefix = new Ip4Prefix("1.2.3.0/24");
+        assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
+
+        ip4prefix = new Ip4Prefix("1.2.3.4/24");
+        assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
+
+        ip4prefix = new Ip4Prefix("1.2.3.5/32");
+        assertThat(ip4prefix.toString(), is("1.2.3.5/32"));
+
+        ip4prefix = new Ip4Prefix("0.0.0.0/0");
+        assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
+
+        ip4prefix = new Ip4Prefix("255.255.255.255/32");
+        assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
+    }
+
+    /**
+     * Tests invalid class constructor for a null string.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullString() {
+        String fromString = null;
+        Ip4Prefix ip4prefix = new Ip4Prefix(fromString);
+    }
+
+    /**
+     * Tests invalid class constructor for an empty string.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructors() {
+        // Check constructor for invalid ID: empty string
+        Ip4Prefix ip4prefix = new Ip4Prefix("");
+    }
+
+    /**
+     * Tests getting the value of an address.
+     */
+    @Test
+    public void testGetValue() {
+        Ip4Prefix ip4prefix = new Ip4Prefix("1.2.3.0/24");
+        assertThat(ip4prefix.getAddress(), equalTo(new Ip4Address("1.2.3.0")));
+        assertThat(ip4prefix.getPrefixLen(), is((short) 24));
+
+        ip4prefix = new Ip4Prefix("0.0.0.0/0");
+        assertThat(ip4prefix.getAddress(), equalTo(new Ip4Address("0.0.0.0")));
+        assertThat(ip4prefix.getPrefixLen(), is((short) 0));
+
+        ip4prefix = new Ip4Prefix("255.255.255.255/32");
+        assertThat(ip4prefix.getAddress(),
+                   equalTo(new Ip4Address("255.255.255.255")));
+        assertThat(ip4prefix.getPrefixLen(), is((short) 32));
+    }
+
+    /**
+     * Tests equality of {@link Ip4Address}.
+     */
+    @Test
+    public void testEquality() {
+        Ip4Prefix addr1net = new Ip4Prefix("1.2.3.0/24");
+        Ip4Prefix addr2net = new Ip4Prefix("1.2.3.0/24");
+        assertThat(addr1net, is(addr2net));
+
+        addr1net = new Ip4Prefix("1.2.3.0/24");
+        addr2net = new Ip4Prefix("1.2.3.4/24");
+        assertThat(addr1net, is(addr2net));
+
+        addr1net = new Ip4Prefix("0.0.0.0/0");
+        addr2net = new Ip4Prefix("0.0.0.0/0");
+        assertThat(addr1net, is(addr2net));
+
+        addr1net = new Ip4Prefix("255.255.255.255/32");
+        addr2net = new Ip4Prefix("255.255.255.255/32");
+        assertThat(addr1net, is(addr2net));
+    }
+
+    /**
+     * Tests non-equality of {@link Ip4Address}.
+     */
+    @Test
+    public void testNonEquality() {
+        Ip4Prefix addr1net = new Ip4Prefix("1.2.0.0/16");
+        Ip4Prefix addr2net = new Ip4Prefix("1.3.0.0/16");
+        Ip4Prefix addr3net = new Ip4Prefix("1.3.0.0/24");
+        Ip4Prefix addr4net = new Ip4Prefix("0.0.0.0/0");
+        Ip4Prefix addr5net = new Ip4Prefix("255.255.255.255/32");
+        assertThat(addr1net, is(not(addr2net)));
+        assertThat(addr3net, is(not(addr2net)));
+        assertThat(addr4net, is(not(addr2net)));
+        assertThat(addr5net, is(not(addr2net)));
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        Ip4Prefix ip4prefix = new Ip4Prefix("1.2.3.0/24");
+        assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
+
+        ip4prefix = new Ip4Prefix("1.2.3.4/24");
+        assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
+
+        ip4prefix = new Ip4Prefix("0.0.0.0/0");
+        assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
+
+        ip4prefix = new Ip4Prefix("255.255.255.255/32");
+        assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
+    }
+}
diff --git a/utils/misc/src/test/java/org/onlab/packet/Ip6AddressTest.java b/utils/misc/src/test/java/org/onlab/packet/Ip6AddressTest.java
new file mode 100644
index 0000000..a053301
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/Ip6AddressTest.java
@@ -0,0 +1,437 @@
+package org.onlab.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Tests for class {@link Ip6Address}.
+ */
+public class Ip6AddressTest {
+    /**
+     * Tests the immutability of {@link Ip6Address}.
+     */
+    @Test
+    public void testImmutable() {
+        assertThatClassIsImmutable(Ip6Address.class);
+    }
+
+    /**
+     * Tests the length of the address in bytes (octets).
+     */
+    @Test
+    public void testAddrBytelen() {
+        assertThat(Ip6Address.BYTE_LENGTH, is(16));
+    }
+
+    /**
+     * Tests the length of the address in bits.
+     */
+    @Test
+    public void testAddrBitlen() {
+        assertThat(Ip6Address.BIT_LENGTH, is(128));
+    }
+
+    /**
+     * Tests default class constructor.
+     */
+    @Test
+    public void testDefaultConstructor() {
+        Ip6Address ip6Address = new Ip6Address();
+        assertThat(ip6Address.toString(), is("::"));
+    }
+
+    /**
+     * Tests valid class copy constructor.
+     */
+    @Test
+    public void testCopyConstructor() {
+        Ip6Address fromAddr =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        Ip6Address ip6Address = new Ip6Address(fromAddr);
+        assertThat(ip6Address.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+        fromAddr = new Ip6Address("::");
+        ip6Address = new Ip6Address(fromAddr);
+        assertThat(ip6Address.toString(), is("::"));
+
+        fromAddr = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        ip6Address = new Ip6Address(fromAddr);
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+    }
+
+    /**
+     * Tests invalid class copy constructor for a null object to copy from.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullObject() {
+        Ip6Address fromAddr = null;
+        Ip6Address ip6Address = new Ip6Address(fromAddr);
+    }
+
+    /**
+     * Tests valid class constructor for integer values.
+     */
+    @Test
+    public void testConstructorForInteger() {
+        Ip6Address ip6Address =
+            new Ip6Address(0x1111222233334444L, 0x5555666677778888L);
+        assertThat(ip6Address.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+        ip6Address = new Ip6Address(0L, 0L);
+        assertThat(ip6Address.toString(), is("::"));
+
+        ip6Address = new Ip6Address(-1L, -1L);
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+    }
+
+    /**
+     * Tests valid class constructor for an array value.
+     */
+    @Test
+    public void testConstructorForArray() {
+        final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22,
+                                          0x33, 0x33, 0x44, 0x44,
+                                          0x55, 0x55, 0x66, 0x66,
+                                          0x77, 0x77,
+                                          (byte) 0x88, (byte) 0x88};
+        Ip6Address ip6Address = new Ip6Address(value1);
+        assertThat(ip6Address.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+        final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00};
+        ip6Address = new Ip6Address(value2);
+        assertThat(ip6Address.toString(), is("::"));
+
+        final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff};
+        ip6Address = new Ip6Address(value3);
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+    }
+
+    /**
+     * Tests valid class constructor for an array value and an offset.
+     */
+    @Test
+    public void testConstructorForArrayAndOffset() {
+        final byte[] value1 = new byte[] {11, 22, 33,           // Preamble
+                                          0x11, 0x11, 0x22, 0x22,
+                                          0x33, 0x33, 0x44, 0x44,
+                                          0x55, 0x55, 0x66, 0x66,
+                                          0x77, 0x77,
+                                          (byte) 0x88, (byte) 0x88,
+                                          44, 55};              // Extra bytes
+        Ip6Address ip6Address = new Ip6Address(value1, 3);
+        assertThat(ip6Address.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+        final byte[] value2 = new byte[] {11, 22,               // Preamble
+                                          0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00,
+                                          33};                  // Extra bytes
+        ip6Address = new Ip6Address(value2, 2);
+        assertThat(ip6Address.toString(), is("::"));
+
+        final byte[] value3 = new byte[] {11, 22,               // Preamble
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          33};                  // Extra bytes
+        ip6Address = new Ip6Address(value3, 2);
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+    }
+
+    /**
+     * Tests invalid class constructor for a null array.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullArray() {
+        final byte[] fromArray = null;
+        Ip6Address ip6Address = new Ip6Address(fromArray);
+    }
+
+    /**
+     * Tests invalid class constructor for an array that is too short.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructorShortArray() {
+        final byte[] fromArray = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
+        Ip6Address ip6Address = new Ip6Address(fromArray);
+    }
+
+    /**
+     * Tests invalid class constructor for an array and an invalid offset.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructorArrayInvalidOffset() {
+        final byte[] value1 = new byte[] {11, 22, 33,           // Preamble
+                                          0x11, 0x11, 0x22, 0x22,
+                                          0x33, 0x33, 0x44, 0x44,
+                                          0x55, 0x55, 0x66, 0x66,
+                                          0x77, 0x77,
+                                          (byte) 0x88, (byte) 0x88,
+                                          44, 55};              // Extra bytes
+        Ip6Address ip6Address = new Ip6Address(value1, 6);
+    }
+
+    /**
+     * Tests valid class constructor for a string.
+     */
+    @Test
+    public void testConstructorForString() {
+        Ip6Address ip6Address =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        assertThat(ip6Address.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+        ip6Address = new Ip6Address("::");
+        assertThat(ip6Address.toString(), is("::"));
+
+        ip6Address = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+    }
+
+    /**
+     * Tests invalid class constructor for a null string.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullString() {
+        String fromString = null;
+        Ip6Address ip6Address = new Ip6Address(fromString);
+    }
+
+    /**
+     * Tests invalid class constructor for an empty string.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructors() {
+        // Check constructor for invalid ID: empty string
+        Ip6Address ip6Address = new Ip6Address("");
+    }
+
+    /**
+     * Tests returning the address as a byte array.
+     */
+    @Test
+    public void testAddressToOctets() {
+        final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22,
+                                          0x33, 0x33, 0x44, 0x44,
+                                          0x55, 0x55, 0x66, 0x66,
+                                          0x77, 0x77,
+                                          (byte) 0x88, (byte) 0x88};
+        Ip6Address ip6Address =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        assertThat(ip6Address.toOctets(), is(value1));
+
+        final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x00};
+        ip6Address = new Ip6Address("::");
+        assertThat(ip6Address.toOctets(), is(value2));
+
+        final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff,
+                                          (byte) 0xff, (byte) 0xff};
+        ip6Address = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        assertThat(ip6Address.toOctets(), is(value3));
+    }
+
+    /**
+     * Tests making a mask prefix for a given prefix length.
+     */
+    @Test
+    public void testMakeMaskPrefix() {
+        Ip6Address ip6Address = Ip6Address.makeMaskPrefix(8);
+        assertThat(ip6Address.toString(), is("ff00::"));
+
+        ip6Address = Ip6Address.makeMaskPrefix(120);
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"));
+
+        ip6Address = Ip6Address.makeMaskPrefix(0);
+        assertThat(ip6Address.toString(), is("::"));
+
+        ip6Address = Ip6Address.makeMaskPrefix(128);
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+
+        ip6Address = Ip6Address.makeMaskPrefix(64);
+        assertThat(ip6Address.toString(), is("ffff:ffff:ffff:ffff::"));
+    }
+
+    /**
+     * Tests making of a masked address.
+     */
+    @Test
+    public void testMakeMaskedAddress() {
+        Ip6Address ip6Address =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885");
+        Ip6Address ip6AddressMasked =
+            Ip6Address.makeMaskedAddress(ip6Address, 8);
+        assertThat(ip6AddressMasked.toString(), is("1100::"));
+
+        ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 120);
+        assertThat(ip6AddressMasked.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8800"));
+
+        ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 0);
+        assertThat(ip6AddressMasked.toString(), is("::"));
+
+        ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 128);
+        assertThat(ip6AddressMasked.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8885"));
+
+        ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 64);
+        assertThat(ip6AddressMasked.toString(), is("1111:2222:3333:4444::"));
+    }
+
+    /**
+     * Tests getting the value of an address.
+     */
+    @Test
+    public void testGetValue() {
+        Ip6Address ip6Address =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        assertThat(ip6Address.getValueHigh(), is(0x1111222233334444L));
+        assertThat(ip6Address.getValueLow(), is(0x5555666677778888L));
+
+        ip6Address = new Ip6Address(0, 0);
+        assertThat(ip6Address.getValueHigh(), is(0L));
+        assertThat(ip6Address.getValueLow(), is(0L));
+
+        ip6Address = new Ip6Address(-1L, -1L);
+        assertThat(ip6Address.getValueHigh(), is(-1L));
+        assertThat(ip6Address.getValueLow(), is(-1L));
+    }
+
+    /**
+     * Tests equality of {@link Ip6Address}.
+     */
+    @Test
+    public void testEquality() {
+        Ip6Address addr1 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        Ip6Address addr2 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        assertThat(addr1, is(addr2));
+
+        addr1 = new Ip6Address("::");
+        addr2 = new Ip6Address("::");
+        assertThat(addr1, is(addr2));
+
+        addr1 = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        addr2 = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        assertThat(addr1, is(addr2));
+    }
+
+    /**
+     * Tests non-equality of {@link Ip6Address}.
+     */
+    @Test
+    public void testNonEquality() {
+        Ip6Address addr1 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        Ip6Address addr2 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:888A");
+        Ip6Address addr3 = new Ip6Address("::");
+        Ip6Address addr4 =
+            new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        assertThat(addr1, is(not(addr2)));
+        assertThat(addr3, is(not(addr2)));
+        assertThat(addr4, is(not(addr2)));
+    }
+
+    /**
+     * Tests comparison of {@link Ip6Address}.
+     */
+    @Test
+    public void testComparison() {
+        Ip6Address addr1 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        Ip6Address addr2 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        Ip6Address addr3 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8887");
+        Ip6Address addr4 =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8889");
+        assertTrue(addr1.compareTo(addr2) == 0);
+        assertTrue(addr1.compareTo(addr3) > 0);
+        assertTrue(addr1.compareTo(addr4) < 0);
+
+        addr1 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
+        addr2 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
+        addr3 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8887");
+        addr4 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8889");
+        assertTrue(addr1.compareTo(addr2) == 0);
+        assertTrue(addr1.compareTo(addr3) > 0);
+        assertTrue(addr1.compareTo(addr4) < 0);
+
+        addr1 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
+        addr2 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
+        addr3 = new Ip6Address("ffff:2222:3333:4443:5555:6666:7777:8888");
+        addr4 = new Ip6Address("ffff:2222:3333:4445:5555:6666:7777:8888");
+        assertTrue(addr1.compareTo(addr2) == 0);
+        assertTrue(addr1.compareTo(addr3) > 0);
+        assertTrue(addr1.compareTo(addr4) < 0);
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        Ip6Address ip6Address =
+            new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
+        assertThat(ip6Address.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+        ip6Address = new Ip6Address("1111::8888");
+        assertThat(ip6Address.toString(), is("1111::8888"));
+
+        ip6Address = new Ip6Address("1111::");
+        assertThat(ip6Address.toString(), is("1111::"));
+
+        ip6Address = new Ip6Address("::8888");
+        assertThat(ip6Address.toString(), is("::8888"));
+
+        ip6Address = new Ip6Address("::");
+        assertThat(ip6Address.toString(), is("::"));
+
+        ip6Address = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        assertThat(ip6Address.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+    }
+}
diff --git a/utils/misc/src/test/java/org/onlab/packet/Ip6PrefixTest.java b/utils/misc/src/test/java/org/onlab/packet/Ip6PrefixTest.java
new file mode 100644
index 0000000..dcacdc7
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/Ip6PrefixTest.java
@@ -0,0 +1,255 @@
+package org.onlab.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Tests for class {@link Ip6Prefix}.
+ */
+public class Ip6PrefixTest {
+    /**
+     * Tests the immutability of {@link Ip6Prefix}.
+     */
+    @Test
+    public void testImmutable() {
+        assertThatClassIsImmutable(Ip6Prefix.class);
+    }
+
+    /**
+     * Tests default class constructor.
+     */
+    @Test
+    public void testDefaultConstructor() {
+        Ip6Prefix ip6prefix = new Ip6Prefix();
+        assertThat(ip6prefix.toString(), is("::/0"));
+    }
+
+    /**
+     * Tests valid class copy constructor.
+     */
+    @Test
+    public void testCopyConstructor() {
+        Ip6Prefix fromAddr = new Ip6Prefix("1100::/8");
+        Ip6Prefix ip6prefix = new Ip6Prefix(fromAddr);
+        assertThat(ip6prefix.toString(), is("1100::/8"));
+
+        fromAddr = new Ip6Prefix("::/0");
+        ip6prefix = new Ip6Prefix(fromAddr);
+        assertThat(ip6prefix.toString(), is("::/0"));
+
+        fromAddr =
+            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        ip6prefix = new Ip6Prefix(fromAddr);
+        assertThat(ip6prefix.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
+    }
+
+    /**
+     * Tests invalid class copy constructor for a null object to copy from.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullObject() {
+        Ip6Prefix fromAddr = null;
+        Ip6Prefix ip6prefix = new Ip6Prefix(fromAddr);
+    }
+
+    /**
+     * Tests valid class constructor for an address and prefix length.
+     */
+    @Test
+    public void testConstructorForAddressAndPrefixLength() {
+        Ip6Prefix ip6prefix =
+            new Ip6Prefix(new Ip6Address("1100::"), (short) 8);
+        assertThat(ip6prefix.toString(), is("1100::/8"));
+
+        ip6prefix =
+            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
+                        (short) 8);
+        assertThat(ip6prefix.toString(), is("1100::/8"));
+
+        ip6prefix =
+            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8800"),
+                        (short) 120);
+        assertThat(ip6prefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
+
+        ip6prefix = new Ip6Prefix(new Ip6Address("::"), (short) 0);
+        assertThat(ip6prefix.toString(), is("::/0"));
+
+        ip6prefix =
+            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
+                        (short) 128);
+        assertThat(ip6prefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8885/128"));
+
+        ip6prefix =
+            new Ip6Prefix(new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
+                        (short) 128);
+        assertThat(ip6prefix.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
+
+        ip6prefix =
+            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
+                        (short) 64);
+        assertThat(ip6prefix.toString(), is("1111:2222:3333:4444::/64"));
+    }
+
+    /**
+     * Tests valid class constructor for a string.
+     */
+    @Test
+    public void testConstructorForString() {
+        Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
+        assertThat(ip6prefix.toString(), is("1100::/8"));
+
+        ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
+        assertThat(ip6prefix.toString(), is("1100::/8"));
+
+        ip6prefix =
+            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8800/120");
+        assertThat(ip6prefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
+
+        ip6prefix = new Ip6Prefix("::/0");
+        assertThat(ip6prefix.toString(), is("::/0"));
+
+        ip6prefix =
+            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/128");
+        assertThat(ip6prefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8885/128"));
+
+        ip6prefix = new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(ip6prefix.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
+
+        ip6prefix =
+            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/64");
+        assertThat(ip6prefix.toString(), is("1111:2222:3333:4444::/64"));
+    }
+
+    /**
+     * Tests invalid class constructor for a null string.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullString() {
+        String fromString = null;
+        Ip6Prefix ip6prefix = new Ip6Prefix(fromString);
+    }
+
+    /**
+     * Tests invalid class constructor for an empty string.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructors() {
+        // Check constructor for invalid ID: empty string
+        Ip6Prefix ip6prefix = new Ip6Prefix("");
+    }
+
+    /**
+     * Tests getting the value of an address.
+     */
+    @Test
+    public void testGetValue() {
+        Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
+        assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("1100::")));
+        assertThat(ip6prefix.getPrefixLen(), is((short) 8));
+
+        ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
+        assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("1100::")));
+        assertThat(ip6prefix.getPrefixLen(), is((short) 8));
+
+        ip6prefix =
+            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8800/120");
+        assertThat(ip6prefix.getAddress(),
+                   equalTo(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8800")));
+        assertThat(ip6prefix.getPrefixLen(), is((short) 120));
+
+        ip6prefix = new Ip6Prefix("::/0");
+        assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("::")));
+        assertThat(ip6prefix.getPrefixLen(), is((short) 0));
+
+        ip6prefix =
+            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/128");
+        assertThat(ip6prefix.getAddress(),
+                   equalTo(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885")));
+        assertThat(ip6prefix.getPrefixLen(), is((short) 128));
+
+        ip6prefix =
+            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(ip6prefix.getAddress(),
+                   equalTo(new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+        assertThat(ip6prefix.getPrefixLen(), is((short) 128));
+
+        ip6prefix =
+            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/64");
+        assertThat(ip6prefix.getAddress(),
+                   equalTo(new Ip6Address("1111:2222:3333:4444::")));
+        assertThat(ip6prefix.getPrefixLen(), is((short) 64));
+    }
+
+    /**
+     * Tests equality of {@link Ip6Address}.
+     */
+    @Test
+    public void testEquality() {
+        Ip6Prefix addr1net = new Ip6Prefix("1100::/8");
+        Ip6Prefix addr2net = new Ip6Prefix("1100::/8");
+        assertThat(addr1net, is(addr2net));
+
+        addr1net = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
+        addr2net = new Ip6Prefix("1100::/8");
+        assertThat(addr1net, is(addr2net));
+
+        addr1net = new Ip6Prefix("::/0");
+        addr2net = new Ip6Prefix("::/0");
+        assertThat(addr1net, is(addr2net));
+
+        addr1net =
+            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        addr2net =
+            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(addr1net, is(addr2net));
+    }
+
+    /**
+     * Tests non-equality of {@link Ip6Address}.
+     */
+    @Test
+    public void testNonEquality() {
+        Ip6Prefix addr1net = new Ip6Prefix("1100::/8");
+        Ip6Prefix addr2net = new Ip6Prefix("1200::/8");
+        Ip6Prefix addr3net = new Ip6Prefix("1200::/12");
+        Ip6Prefix addr4net = new Ip6Prefix("::/0");
+        Ip6Prefix addr5net =
+            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(addr1net, is(not(addr2net)));
+        assertThat(addr3net, is(not(addr2net)));
+        assertThat(addr4net, is(not(addr2net)));
+        assertThat(addr5net, is(not(addr2net)));
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
+        assertThat(ip6prefix.toString(), is("1100::/8"));
+
+        ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
+        assertThat(ip6prefix.toString(), is("1100::/8"));
+
+        ip6prefix = new Ip6Prefix("::/0");
+        assertThat(ip6prefix.toString(), is("::/0"));
+
+        ip6prefix =
+            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(ip6prefix.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
+    }
+}