Merge remote-tracking branch 'origin/master'
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
index a10e710..73bb9c9 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
@@ -234,6 +234,30 @@
         return mask() != 0;
     }
 
+    /**
+     * Determines whether a given address is contained within this IpAddress'
+     * network.
+     *
+     * @param other another IP address that could be contained in this network
+     * @return true if the other IP address is contained in this address'
+     * network, otherwise false
+     */
+    public boolean contains(IpAddress other) {
+        if (this.netmask <= other.netmask) {
+            // Special case where they're both /32 addresses
+            if (this.netmask == MAX_INET_MASK) {
+                return Arrays.equals(octets, other.octets);
+            }
+
+            // Mask the other address with our network mask
+            IpAddress otherMasked =
+                    IpAddress.valueOf(other.octets, netmask).network();
+
+            return network().equals(otherMasked);
+        }
+        return false;
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
diff --git a/utils/misc/src/test/java/org/onlab/packet/IPAddressTest.java b/utils/misc/src/test/java/org/onlab/packet/IPAddressTest.java
index f1a7b0d..d503229 100644
--- a/utils/misc/src/test/java/org/onlab/packet/IPAddressTest.java
+++ b/utils/misc/src/test/java/org/onlab/packet/IPAddressTest.java
@@ -1,6 +1,7 @@
 package org.onlab.packet;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import java.util.Arrays;
@@ -73,4 +74,26 @@
         assertTrue("incorrect netmask",
                 Arrays.equals(IpAddress.ANY, ip2.netmask().toOctets()));
     }
+
+    @Test
+    public void testContains() {
+        IpAddress slash31 = IpAddress.valueOf(BYTES1, 31);
+        IpAddress slash32 = IpAddress.valueOf(BYTES1, 32);
+        IpAddress differentSlash32 = IpAddress.valueOf(BYTES2, 32);
+
+        assertTrue(slash31.contains(differentSlash32));
+        assertFalse(differentSlash32.contains(slash31));
+
+        assertTrue(slash31.contains(slash32));
+        assertFalse(slash32.contains(differentSlash32));
+        assertFalse(differentSlash32.contains(slash32));
+
+        IpAddress zero = IpAddress.valueOf("0.0.0.0/0");
+        assertTrue(zero.contains(differentSlash32));
+        assertFalse(differentSlash32.contains(zero));
+
+        IpAddress slash8 = IpAddress.valueOf("10.0.0.0/8");
+        assertTrue(slash8.contains(slash31));
+        assertFalse(slash31.contains(slash8));
+    }
 }