Address review comments
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
index 54465bf..c96be83 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
@@ -10,14 +10,13 @@
      * @return true if this represents a valid CIDR style netmask, false
      * otherwise
      */
-    public boolean isCidrMask() {
-        return asCidrMaskLength() != -1;
-    }
+    public abstract boolean isCidrMask();
 
     /**
      * If this IPAddress represents a valid CIDR style netmask (see
      * isCidrMask()) returns the length of the prefix (the number of "1" bits).
-     * @return length of CIDR mask or -1 if this is not a CIDR netmask
+     * @return length of CIDR mask if this represents a valid CIDR mask
+     * @throws IllegalStateException if isCidrMask() == false
      */
     public abstract int asCidrMaskLength();
 
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
index 654e72c..2087ab4 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
@@ -27,7 +27,7 @@
         res.append(value.toString());
 
         res.append('/');
-        if (mask.asCidrMaskLength() != -1) {
+        if (mask.isCidrMask()) {
             // CIDR notation
             res.append(mask.asCidrMaskLength());
         } else {
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
index 87167fb..2505d56 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
@@ -18,6 +18,11 @@
     static final int LENGTH = 4;
     private final int rawValue;
 
+    private static int NOT_A_CIDR_MASK = -1;
+    private static int CIDR_MASK_CACHE_UNSET = -2;
+    // Must appear before the static IPv4Address constant assignments
+    private volatile int cidrMaskLengthCache = CIDR_MASK_CACHE_UNSET;
+
     private final static int NONE_VAL = 0x0;
     public final static IPv4Address NONE = new IPv4Address(NONE_VAL);
 
@@ -33,18 +38,34 @@
         return IPVersion.IPv4;
     }
 
+    private int asCidrMaskLengthInternal() {
+        if (cidrMaskLengthCache == CIDR_MASK_CACHE_UNSET) {
+            // No lock required. We only write cidrMaskLengthCache once
+            int maskint = getInt();
+            if (maskint == 0) {
+                cidrMaskLengthCache = 0;
+            } else if (Integer.bitCount((~maskint) + 1) == 1) {
+                // IP represents a true CIDR prefix length
+                cidrMaskLengthCache = Integer.bitCount(maskint);
+            } else {
+                cidrMaskLengthCache = NOT_A_CIDR_MASK;
+            }
+        }
+        return cidrMaskLengthCache;
+    }
+
+    @Override
+    public boolean isCidrMask() {
+        return asCidrMaskLengthInternal() != NOT_A_CIDR_MASK;
+    }
 
     @Override
     public int asCidrMaskLength() {
-        int maskint = getInt();
-        if (maskint == 0)
-            return 0;
-        else if (Integer.bitCount((~maskint) + 1) == 1) {
-            // IP represents a true CIDR prefix length
-            return Integer.bitCount(maskint);
+        if (!isCidrMask()) {
+            throw new IllegalStateException("IP is not a valid CIDR prefix " +
+                    "mask " + toString());
         } else {
-            // IP is not a true prefix.
-            return -1;
+            return asCidrMaskLengthInternal();
         }
     }
 
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
index 63ae700..b69035c 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
@@ -1,11 +1,9 @@
 package org.projectfloodlight.openflow.types;
 
-import java.math.BigInteger;
 import java.util.regex.Pattern;
 
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
-
 import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Longs;
 
@@ -20,10 +18,16 @@
     private final long raw1;
     private final long raw2;
 
+    private static int NOT_A_CIDR_MASK = -1;
+    private static int CIDR_MASK_CACHE_UNSET = -2;
+    // Must appear before the static IPv4Address constant assignments
+    private volatile int cidrMaskLengthCache = CIDR_MASK_CACHE_UNSET;
+
     private final static long NONE_VAL1 = 0x0L;
     private final static long NONE_VAL2 = 0x0L;
     public static final IPv6Address NONE = new IPv6Address(NONE_VAL1, NONE_VAL2);
 
+
     public static final IPv6Address NO_MASK = IPv6Address.of(0xFFFFFFFFFFFFFFFFl, 0xFFFFFFFFFFFFFFFFl);
     public static final IPv6Address FULL_MASK = IPv6Address.of(0x0, 0x0);
 
@@ -38,17 +42,52 @@
     }
 
 
+    private int computeCidrMask64(long raw) {
+        long mask = raw;
+        if (raw == 0)
+            return 0;
+        else if (Long.bitCount((~mask) + 1L) == 1L) {
+            // represent a true CIDR prefix length
+            return Long.bitCount(mask);
+        }
+        else {
+            // Not a true prefix
+            return NOT_A_CIDR_MASK;
+        }
+    }
+
+    private int asCidrMaskLengthInternal() {
+        if (cidrMaskLengthCache == CIDR_MASK_CACHE_UNSET) {
+            synchronized (this) {
+                if (raw1 == 0 && raw2 == 0) {
+                    cidrMaskLengthCache = 0;
+                } else if (raw1 == -1) {
+                    // top half is all 1 bits
+                    cidrMaskLengthCache = computeCidrMask64(raw2);
+                    if (cidrMaskLengthCache != NOT_A_CIDR_MASK)
+                        cidrMaskLengthCache += 64;
+                } else if (raw2 == 0) {
+                    cidrMaskLengthCache = computeCidrMask64(raw1);
+                } else {
+                    cidrMaskLengthCache = NOT_A_CIDR_MASK;
+                }
+            }
+        }
+        return cidrMaskLengthCache;
+    }
+
+    @Override
+    public boolean isCidrMask() {
+        return asCidrMaskLengthInternal() != NOT_A_CIDR_MASK;
+    }
+
     @Override
     public int asCidrMaskLength() {
-        BigInteger maskBigint = new BigInteger(getBytes());
-        if (maskBigint.equals(BigInteger.ZERO))
-            return 0; // Thanks, signed BigInteger
-        else if (maskBigint.not().add(BigInteger.ONE).bitCount() == 1) {
-            // Need to get a positive BigInteger before we can count
-            return new BigInteger(1, getBytes()).bitCount();
+        if (!isCidrMask()) {
+            throw new IllegalStateException("IP is not a valid CIDR prefix " +
+                    "mask " + toString());
         } else {
-            // IP is not a true prefix.
-            return -1;
+            return asCidrMaskLengthInternal();
         }
     }