1. Removed type serializers, added (write|read)[0-9]*Byte[s]?(ChannelBuffer) method to value types instead.
2. Updated Masked fields for IPv4, IPv6 with specific string methods.
3. Added value types for other fields from the spec
4. Updated unit tests accordingly
5. Changed java_type.py to support multiple read/write operations per type, per OF version.
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index e88458a..8580f37 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -21,6 +21,19 @@
         return camel
 
 
+ANY = 0xFFFFFFFFFFFFFFFF
+
+
+class VersionOp:
+    def __init__(self, version=ANY, read=None, write=None):
+        self.version = version
+        self.read = read
+        self.write = write
+        
+    def __str__(self):
+        return "[Version: %d, Read: '%s', Write: '%s']" % (self.version, self.read, self.write)
+
+
 class JType(object):
     """ Wrapper class to hold C to Java type conversion information """
     def __init__(self, pub_type, priv_type=None, size=None, read_op=None, write_op=None):
@@ -29,12 +42,17 @@
             priv_type = pub_type
         self.priv_type = priv_type  # the internal storage type
         self.size = size            # bytes on the wire; None == variable length or hard to calc
-        if read_op is None:
-            read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
-        if write_op is None:
-            write_op = 'ChannelUtils.write%s(bb, $name)'  % self.pub_type
-        self._read_op = read_op
-        self._write_op = write_op
+        self.ops = {}
+#        if read_op is None:
+#            read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
+#        if write_op is None:
+#            write_op = 'ChannelUtils.write%s(bb, $name)'  % self.pub_type
+#        self._read_op = read_op
+#        self._write_op = write_op
+
+    def op(self, version=ANY, read=None, write=None):
+        self.ops[version] = VersionOp(version, read, write)
+        return self
 
     @property
     def public_type(self):
@@ -53,105 +71,111 @@
         if length is None:
             length = "length - bb.readerIndex()";
 
-        if callable(self._read_op):
-            return self._read_op(version)
+        ver = ANY if version is None else version.int_version
+        _read_op = None
+        if ver in self.ops:
+            _read_op = self.ops[ver].read or self.ops[ANY].read 
+        elif ANY in self.ops:
+            _read_op = self.ops[ANY].read
+        if _read_op is None:
+            _read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
+        if callable(_read_op):
+            return _read_op(version)
         else:
-            return self._read_op.replace("$length", str(length)).replace("$version", version.of_version)
+            return _read_op.replace("$length", str(length)).replace("$version", version.of_version)
 
     def write_op(self, version=None, name=None):
-        if callable(self._write_op):
-            return self._write_op(version, name)
+        ver = ANY if version is None else version.int_version
+        _write_op = None
+        if ver in self.ops:
+            _write_op = self.ops[ver].write or self.ops[ANY].write
+        elif ANY in self.ops:
+            _write_op = self.ops[ANY].write
+        if _write_op is None:
+            _write_op = 'ChannelUtils.write%s(bb, $name)' % self.pub_type
+        if callable(_write_op):
+            return _write_op(version, name)
         else:
-            return self._write_op.replace("$name", str(name)).replace("$version", version.of_version)
+            return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
 
-hello_elem_list = JType("List<OFHelloElement>",
-        read_op = 'ChannelUtils.readHelloElementList(bb)',
-        write_op = 'ChannelUtils.writeHelloElementList(bb)'
-        )
-u8 =  JType('byte',  size=1, read_op='bb.readByte()',
-        write_op='bb.writeByte($name)')
-u8_list =  JType('List<U8>',  size=1, read_op='bb.readByte()',
-        write_op='bb.writeByte($name)')
-u16 = JType('int', 'int', size=2, read_op='U16.f(bb.readShort())',
-        write_op='bb.writeShort(U16.t($name))')
-u32 = JType('int', 'int',   size=4, read_op='bb.readInt()',
-        write_op='bb.writeInt($name)')
-u32_list = JType('List<U32>', 'int[]',   size=4, read_op='bb.readInt()',
-        write_op='bb.writeInt($name)')
-u64 = JType('U64', 'U64', size=8, read_op='U64.of(bb.readLong())',
-        write_op='bb.writeLong($name.getValue())')
-of_port= JType('OFPort',size=None,
-        read_op = "OFPort.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "OFPort.SERIALIZER_V$version.writeTo($name, bb)")
-one_byte_array = JType('byte[]', size=1,
-        read_op = 'ChannelUtils.readBytes(bb, 1)',
-        write_op = 'ChannelUtils.writeBytes(bb, $name)')
-two_byte_array = JType('byte[]', size=2,
-        read_op = 'ChannelUtils.readBytes(bb, 2)',
-        write_op = 'ChannelUtils.writeBytes(bb, $name)')
-three_byte_array = JType('byte[]', size=3,
-        read_op = 'ChannelUtils.readBytes(bb, 3)',
-        write_op = 'ChannelUtils.writeBytes(bb, $name)')
-four_byte_array = JType('byte[]', size=4,
-        read_op = 'ChannelUtils.readBytes(bb, 4)',
-        write_op = 'ChannelUtils.writeBytes(bb, $name)')
-five_byte_array = JType('byte[]', size=5,
-        read_op = 'ChannelUtils.readBytes(bb, 5)',
-        write_op = 'ChannelUtils.writeBytes(bb, $name)')
-six_byte_array = JType('byte[]', size=6,
-        read_op = 'ChannelUtils.readBytes(bb, 6)',
-        write_op = 'ChannelUtils.writeBytes(bb, $name)')
-seven_byte_array = JType('byte[]', size=7,
-        read_op = 'ChannelUtils.readBytes(bb, 7)',
-        write_op = 'ChannelUtils.writeBytes(bb, $name)')
-actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readActionsList(bb, $length)',
-        write_op = 'ChannelUtils.writeActionsList(bb, $name);')
-instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readInstructionsList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readBucketList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readPhysicalPortList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-port_desc = JType('OFPortDesc', size='$name.getLength()',
-        read_op = 'null; // TODO OFPortDescVer$version.READER.read(bb)',
-        write_op = '$name.writeTo(bb)')
-packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readPacketQueueList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-octets = JType('byte[]', size="$length",
-        read_op = 'ChannelUtils.readBytes(bb, $length)',
-        write_op = 'bb.writeBytes($name)')
-of_match = JType('Match', size="$name.getLength()",
-        read_op = 'ChannelUtils.readOFMatch(bb)',
-        write_op = 'ChannelUtils.writeOFMatch(bb, $name)')
-flow_mod_cmd = JType('OFFlowModCommand', 'short', size="$name.getLength()",
-        read_op = lambda v: "bb.readShort()" if v.int_version == 1 else "bb.readByte()",
-        write_op = lambda v, name: "bb.writeShort(%s)" % name if v.int_version == 1 else "bb.writeByte(%s)" % name)
-mac_addr = JType('MacAddress', 'byte[]', size=6,
-        read_op = "MacAddress.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "MacAddress.SERIALIZER_V$version.writeTo($name, bb)")
-port_name = JType('String', size=16,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 16)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 16)')
-desc_str = JType('String', size=256,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 256)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 256)')
-serial_num = JType('String', size=32,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
-table_name = JType('String', size=32,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
-ipv4 = JType("IPv4",
-        read_op = "IPv4.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "IPv4.SERIALIZER_V$version.writeTo($name, bb)")
-ipv6 = JType("IPv6",
-        read_op = "IPv6.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "IPv6.SERIALIZER_V$version.writeTo($name, bb)")
+hello_elem_list = JType("List<OFHelloElement>") \
+        .op(read='ChannelUtils.readHelloElementList(bb)', write='ChannelUtils.writeHelloElementList(bb)')
+u8 =  JType('byte',  size=1) \
+        .op(read='bb.readByte()', write='bb.writeByte($name)')
+u8_list =  JType('List<U8>',  size=1) \
+        .op(read='bb.readByte()', write='bb.writeByte($name)')
+u16 = JType('int', 'int', size=2) \
+        .op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))')
+u32 = JType('int', 'int', size=4) \
+        .op(read='bb.readInt()', write='bb.writeInt($name)')
+u32_list = JType('List<U32>', 'int[]', size=4) \
+        .op(read='bb.readInt()', write='bb.writeInt($name)')
+u64 = JType('U64', 'U64', size=8) \
+        .op(read='U64.of(bb.readLong())', write='bb.writeLong($name.getValue())')
+of_port = JType("OFPort") \
+         .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)") \
+         .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)")
+one_byte_array = JType('byte[]', size=1) \
+        .op(read='ChannelUtils.readBytes(bb, 1)', write='ChannelUtils.writeBytes(bb, $name)')
+two_byte_array = JType('byte[]', size=2) \
+        .op(read='ChannelUtils.readBytes(bb, 2)', write='ChannelUtils.writeBytes(bb, $name)')
+three_byte_array = JType('byte[]', size=3) \
+        .op(read='ChannelUtils.readBytes(bb, 3)', write='ChannelUtils.writeBytes(bb, $name)')
+four_byte_array = JType('byte[]', size=4) \
+        .op(read='ChannelUtils.readBytes(bb, 4)', write='ChannelUtils.writeBytes(bb, $name)')
+five_byte_array = JType('byte[]', size=5) \
+        .op(read='ChannelUtils.readBytes(bb, 5)', write='ChannelUtils.writeBytes(bb, $name)')
+six_byte_array = JType('byte[]', size=6) \
+        .op(read='ChannelUtils.readBytes(bb, 6)', write='ChannelUtils.writeBytes(bb, $name)')
+seven_byte_array = JType('byte[]', size=7) \
+        .op(read='ChannelUtils.readBytes(bb, 7)', write='ChannelUtils.writeBytes(bb, $name)')
+actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readActionsList(bb, $length)', write='ChannelUtils.writeActionsList(bb, $name);')
+instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readInstructionsList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readBucketList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readPhysicalPortList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+port_desc = JType('OFPortDesc', size='$name.getLength()') \
+        .op(read='null; // TODO OFPortDescVer$version.READER.read(bb)', \
+            write='$name.writeTo(bb)')
+packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readPacketQueueList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+octets = JType('byte[]', size="$length") \
+        .op(read='ChannelUtils.readBytes(bb, $length)', \
+            write='bb.writeBytes($name)')
+of_match = JType('Match', size="$name.getLength()") \
+        .op(read='ChannelUtils.readOFMatch(bb)', \
+            write='ChannelUtils.writeOFMatch(bb, $name)')
+flow_mod_cmd = JType('OFFlowModCommand', 'short', size="$name.getLength()") \
+        .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \
+        .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)")
+mac_addr = JType('MacAddress', 'byte[]', size=6) \
+        .op(read="MacAddress.read6Bytes(bb)", \
+            write="$name.write6Bytes(bb)")
+port_name = JType('String', size=16) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 16)')
+desc_str = JType('String', size=256) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 256)')
+serial_num = JType('String', size=32) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+table_name = JType('String', size=32) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+ipv4 = JType("IPv4") \
+        .op(read="IPv4.read4Bytes(bb)", \
+            write="$name.write4Bytes(bb)")
+ipv6 = JType("IPv6") \
+        .op(read="IPv6.read16Bytes(bb)", \
+            write="$name.write16Bytes(bb)")
 
 default_mtype_to_jtype_convert_map = {
         'uint8_t' : u8,
@@ -201,10 +225,9 @@
         raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
     base_name = m.group(1)
     java_base_name = name_c_to_caps_camel(base_name)
-    return JType("List<OF%s>" % java_base_name,
-        read_op = 'ChannelUtils.read%sList(bb)' % java_base_name,
-        write_op = 'ChannelUtils.write%sList(bb, $name)' % java_base_name
-        )
+    return JType("List<OF%s>" % java_base_name) \
+        .op(read='ChannelUtils.read%sList(bb)' % java_base_name, \
+            write='ChannelUtils.write%sList(bb, $name)' % java_base_name)
 
 def convert_to_jtype(obj_name, field_name, c_type):
     """ Convert from a C type ("uint_32") to a java type ("U32")
@@ -212,14 +235,14 @@
     if obj_name in exceptions and field_name in exceptions[obj_name]:
         return exceptions[obj_name][field_name]
     elif field_name == "type" and c_type == "uint8_t":
-        return JType("OFType", 'byte', size=1, read_op='bb.readByte()',
-        write_op='bb.writeByte($name)')
+        return JType("OFType", 'byte', size=1) \
+            .op(read='bb.readByte()', write='bb.writeByte($name)')
     elif field_name == "type" and re.match(r'of_action.*', obj_name):
-        return JType("OFActionType", 'short', size=2, read_op='bb.readShort()',
-        write_op='bb.writeShort($name)')
+        return JType("OFActionType", 'short', size=2) \
+            .op(read='bb.readShort()', write='bb.writeShort($name)')
     elif field_name == "version" and c_type == "uint8_t":
-        return JType("OFVersion", 'byte', size=1, read_op='bb.readByte()',
-        write_op='bb.writeByte($name)')
+        return JType("OFVersion", 'byte', size=1) \
+            .op(read='bb.readByte()', write='bb.writeByte($name)')
     elif c_type in default_mtype_to_jtype_convert_map:
         return default_mtype_to_jtype_convert_map[c_type]
     elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
index 5c1e7b5..fa42737 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
@@ -1,21 +1,20 @@
 package org.openflow.protocol.match;
 
 import org.openflow.protocol.OFObject;
+import org.openflow.types.OFValueType;
 
 public interface Match extends OFObject {
-    public <F> F get(MatchField<F, ?> match);
+    public <F extends OFValueType> F get(MatchField<F> match);
 
-    public <M> M getMasked(MatchField<?, M> match);
+    public boolean supports(MatchField<?> field);
 
-    public boolean supports(MatchField<?, ?> field);
+    public boolean supportsMasked(MatchField<?> field);
 
-    public boolean supportsMasked(MatchField<?, ?> field);
+    public boolean isExact(MatchField<?> field);
 
-    public boolean isExact(MatchField<?, ?> field);
+    public boolean isFullyWildcarded(MatchField<?> field);
 
-    public boolean isFullyWildcarded(MatchField<?, ?> field);
-
-    public boolean isPartiallyMasked(MatchField<?, ?> field);
+    public boolean isPartiallyMasked(MatchField<?> field);
 
     public MatchBuilder getBuilder();
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java
index 7a5e57c..3c601f8 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java
@@ -1,9 +1,11 @@
 package org.openflow.protocol.match;
 
-public interface MatchBuilder extends Match {
-    public <F> MatchBuilder set(MatchField<F, ?> match, F value);
+import org.openflow.types.OFValueType;
 
-    public <M> void setMasked(MatchField<?, M> match, M value);
+public interface MatchBuilder extends Match {
+    public <F extends OFValueType> MatchBuilder set(MatchField<F> match, F value);
+
+    //public <M> void setMasked(MatchField<?, M> match, M value);
 
     public Match getMatch();
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
index f00e1b4..0fbe84b 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
@@ -1,12 +1,13 @@
 package org.openflow.protocol.match;
 
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.types.IpDscp;
 import org.openflow.types.EthType;
 import org.openflow.types.IPv4;
+import org.openflow.types.IpDscp;
 import org.openflow.types.IpProtocol;
 import org.openflow.types.MacAddress;
 import org.openflow.types.OFPort;
+import org.openflow.types.OFValueType;
 import org.openflow.types.U16;
 import org.openflow.types.VlanPcp;
 import org.openflow.types.VlanVid;
@@ -65,7 +66,7 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    public <F> F get(final MatchField<F, ?> match) {
+    public <F extends OFValueType> F get(final MatchField<F> match) {
         switch (match.id) {
             case 0:
                 return (F) inputPort;
@@ -78,7 +79,7 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    public <F> MatchBuilder set(final MatchField<F, ?> match, final F value) {
+    public <F extends OFValueType> MatchBuilder set(final MatchField<F> match, final F value) {
         switch (match.id) {
             case 0:
                 inputPort = (OFPort) value;
@@ -107,37 +108,31 @@
     }
 
     @Override
-    public <M> M getMasked(final MatchField<?, M> match) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean supports(final MatchField<?, ?> field) {
+    public boolean supports(final MatchField<?> field) {
         // TODO Auto-generated method stub
         return false;
     }
 
     @Override
-    public boolean supportsMasked(final MatchField<?, ?> field) {
+    public boolean supportsMasked(final MatchField<?> field) {
         // TODO Auto-generated method stub
         return false;
     }
 
     @Override
-    public boolean isExact(final MatchField<?, ?> field) {
+    public boolean isExact(final MatchField<?> field) {
         // TODO Auto-generated method stub
         return false;
     }
 
     @Override
-    public boolean isFullyWildcarded(final MatchField<?, ?> field) {
+    public boolean isFullyWildcarded(final MatchField<?> field) {
         // TODO Auto-generated method stub
         return false;
     }
 
     @Override
-    public boolean isPartiallyMasked(final MatchField<?, ?> field) {
+    public boolean isPartiallyMasked(final MatchField<?> field) {
         // TODO Auto-generated method stub
         return false;
     }
@@ -159,13 +154,13 @@
         // TODO Auto-generated method stub
 
     }
-
+/*
     @Override
     public <M> void setMasked(final MatchField<?, M> match, final M value) {
         // TODO Auto-generated method stub
 
     }
-
+*/
     @Override
     public Match getMatch() {
         // TODO Auto-generated method stub
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
index cc191ab..d9d68ec 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
@@ -1,18 +1,24 @@
 package org.openflow.protocol.match;
 
+import org.openflow.types.ArpOpcode;
 import org.openflow.types.EthType;
-import org.openflow.types.IPv4;
-import org.openflow.types.IPv6;
+import org.openflow.types.ICMPv4Code;
+import org.openflow.types.ICMPv4Type;
+import org.openflow.types.IPv4WithMask;
+import org.openflow.types.IPv6FlowLabel;
+import org.openflow.types.IPv6WithMask;
+import org.openflow.types.IpDscp;
+import org.openflow.types.IpEcn;
 import org.openflow.types.IpProtocol;
 import org.openflow.types.MacAddress;
 import org.openflow.types.Masked;
 import org.openflow.types.OFPort;
-import org.openflow.types.U16;
-import org.openflow.types.U8;
+import org.openflow.types.OFValueType;
+import org.openflow.types.TransportPort;
 import org.openflow.types.VlanPcp;
 import org.openflow.types.VlanVid;
 
-public class MatchField<F, M> {
+public class MatchField<F extends OFValueType> {
     private final String name;
     public final int id;
 
@@ -26,78 +32,77 @@
         this.id = id;
     }
 
-    public final static MatchField<OFPort, NoMatch> IN_PORT =
-            new MatchField<OFPort, NoMatch>("in_port", 0);
-    public final static MatchField<OFPort, NoMatch> IN_PHY_PORT =
-            new MatchField<OFPort, NoMatch>("in_phy_port");
-    public final static MatchField<OFPort, NoMatch> METADATA =
-            new MatchField<OFPort, NoMatch>("metadata");
+    public final static MatchField<OFPort> IN_PORT =
+            new MatchField<OFPort>("in_port", 0);
+    public final static MatchField<OFPort> IN_PHY_PORT =
+            new MatchField<OFPort>("in_phy_port");
+    public final static MatchField<OFPort> METADATA =
+            new MatchField<OFPort>("metadata");
 
-    public final static MatchField<MacAddress, Masked<MacAddress>> ETH_DST =
-            new MatchField<MacAddress, Masked<MacAddress>>("eth_dst");
-    public final static MatchField<MacAddress, Masked<MacAddress>> ETH_SRC =
-            new MatchField<MacAddress, Masked<MacAddress>>("eth_src", 1);
+    public final static MatchField<Masked<MacAddress>> ETH_DST =
+            new MatchField<Masked<MacAddress>>("eth_dst");
+    public final static MatchField<Masked<MacAddress>> ETH_SRC =
+            new MatchField<Masked<MacAddress>>("eth_src", 1);
 
-    public final static MatchField<EthType, NoMatch> ETH_TYPE =
-            new MatchField<EthType, NoMatch>("eth_type");
+    public final static MatchField<EthType> ETH_TYPE =
+            new MatchField<EthType>("eth_type");
     
-    public final static MatchField<VlanVid, Masked<VlanVid>> VLAN_VID =
-            new MatchField<VlanVid, Masked<VlanVid>>("vlan_vid");
-    public final static MatchField<VlanPcp, NoMatch> VLAN_PCP =
-            new MatchField<VlanPcp, NoMatch>("vlan_pcp");
+    public final static MatchField<Masked<VlanVid>> VLAN_VID =
+            new MatchField<Masked<VlanVid>>("vlan_vid");
+    public final static MatchField<VlanPcp> VLAN_PCP =
+            new MatchField<VlanPcp>("vlan_pcp");
     
     
-    public final static MatchField<NoMatch, NoMatch> IP_DSCP =
-            new MatchField<NoMatch, NoMatch>("ip_dscp");
-    public final static MatchField<NoMatch, NoMatch> IP_ECN =
-            new MatchField<NoMatch, NoMatch>("ip_dscp");
-    public final static MatchField<IpProtocol, NoMatch> IP_PROTO =
-            new MatchField<IpProtocol, NoMatch>("ip_proto");
+    public final static MatchField<IpDscp> IP_DSCP =
+            new MatchField<IpDscp>("ip_dscp");
+    public final static MatchField<IpEcn> IP_ECN =
+            new MatchField<IpEcn>("ip_dscp");
+    public final static MatchField<IpProtocol> IP_PROTO =
+            new MatchField<IpProtocol>("ip_proto");
 
-    public final static MatchField<IPv4, Masked<IPv4>> IPV4_SRC =
-            new MatchField<IPv4, Masked<IPv4>>("ipv4_src");
-    public final static MatchField<IPv4, Masked<IPv4>> IPV4_DST =
-            new MatchField<IPv4, Masked<IPv4>>("ipv4_dst");
+    public final static MatchField<IPv4WithMask> IPV4_SRC =
+            new MatchField<IPv4WithMask>("ipv4_src");
+    public final static MatchField<IPv4WithMask> IPV4_DST =
+            new MatchField<IPv4WithMask>("ipv4_dst");
 
-    public final static MatchField<U16, NoMatch> TCP_SRC = new MatchField<U16, NoMatch>(
+    public final static MatchField<TransportPort> TCP_SRC = new MatchField<TransportPort>(
             "tcp_src");
-    public final static MatchField<U16, NoMatch> TCP_DST = new MatchField<U16, NoMatch>(
+    public final static MatchField<TransportPort> TCP_DST = new MatchField<TransportPort>(
             "tcp_dst");
 
-    public final static MatchField<U16, NoMatch> UDP_SRC = new MatchField<U16, NoMatch>(
+    public final static MatchField<TransportPort> UDP_SRC = new MatchField<TransportPort>(
             "udp_src");
-    public final static MatchField<U16, NoMatch> UDP_DST = new MatchField<U16, NoMatch>(
+    public final static MatchField<TransportPort> UDP_DST = new MatchField<TransportPort>(
             "udp_dst");
 
-    public final static MatchField<U16, NoMatch> SCTP_SRC = new MatchField<U16, NoMatch>(
+    public final static MatchField<TransportPort> SCTP_SRC = new MatchField<TransportPort>(
             "sctp_src");
-    public final static MatchField<U16, NoMatch> SCTP_DST = new MatchField<U16, NoMatch>(
+    public final static MatchField<TransportPort> SCTP_DST = new MatchField<TransportPort>(
             "sctp_dst");
 
-    public final static MatchField<U8, NoMatch> ICMPV4_TYPE = new MatchField<U8, NoMatch>(
+    public final static MatchField<ICMPv4Type> ICMPV4_TYPE = new MatchField<ICMPv4Type>(
             "icmpv4_src");
-    public final static MatchField<U8, NoMatch> ICMPV4_CODE = new MatchField<U8, NoMatch>(
+    public final static MatchField<ICMPv4Code> ICMPV4_CODE = new MatchField<ICMPv4Code>(
             "icmpv4_dst");
 
-    public final static MatchField<U16, NoMatch> ARP_OP = new MatchField<U16, NoMatch>(
+    public final static MatchField<ArpOpcode> ARP_OP = new MatchField<ArpOpcode>(
             "arp_op");
-    public final static MatchField<IPv4, Masked<IPv4>> ARP_SPA =
-            new MatchField<IPv4, Masked<IPv4>>("arp_spa");
-    public final static MatchField<IPv4, Masked<IPv4>> ARP_TPA =
-            new MatchField<IPv4, Masked<IPv4>>("arp_tpa");
-    public final static MatchField<MacAddress, Masked<MacAddress>> ARP_SHA =
-            new MatchField<MacAddress, Masked<MacAddress>>("arp_sha");
-    public final static MatchField<MacAddress, Masked<MacAddress>> ARP_THA =
-            new MatchField<MacAddress, Masked<MacAddress>>("arp_tha");
+    public final static MatchField<IPv4WithMask> ARP_SPA =
+            new MatchField<IPv4WithMask>("arp_spa");
+    public final static MatchField<IPv4WithMask> ARP_TPA =
+            new MatchField<IPv4WithMask>("arp_tpa");
+    public final static MatchField<Masked<MacAddress>> ARP_SHA =
+            new MatchField<Masked<MacAddress>>("arp_sha");
+    public final static MatchField<Masked<MacAddress>> ARP_THA =
+            new MatchField<Masked<MacAddress>>("arp_tha");
 
-    public final static MatchField<IPv6, Masked<IPv6>> IPV6_SRC =
-            new MatchField<IPv6, Masked<IPv6>>("ipv6_src");
-    public final static MatchField<IPv6, Masked<IPv6>> IPV6_DST =
-            new MatchField<IPv6, Masked<IPv6>>("ipv6_dst");
+    public final static MatchField<IPv6WithMask> IPV6_SRC =
+            new MatchField<IPv6WithMask>("ipv6_src");
+    public final static MatchField<IPv6WithMask> IPV6_DST =
+            new MatchField<IPv6WithMask>("ipv6_dst");
 
-    // FIXME: Wrong masked type?
-    public final static MatchField<U8, Masked<IPv6>> IPV6_FLABEL =
-            new MatchField<U8, Masked<IPv6>>("ipv6_flabel");
+    public final static MatchField<Masked<IPv6FlowLabel>> IPV6_FLABEL =
+            new MatchField<Masked<IPv6FlowLabel>>("ipv6_flabel");
 
     public String getName() {
         return name;
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/NoMatch.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/NoMatch.java
deleted file mode 100644
index b314a59..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/NoMatch.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.openflow.protocol.match;
-
-public class NoMatch {
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/types/IpDscp.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/types/IpDscp.java
deleted file mode 100644
index dcc242a..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/types/IpDscp.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.openflow.protocol.types;
-
-public class IpDscp {
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/ArpOpcode.java b/java_gen/pre-written/src/main/java/org/openflow/types/ArpOpcode.java
new file mode 100644
index 0000000..852aa20
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/ArpOpcode.java
@@ -0,0 +1,145 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class ArpOpcode implements OFValueType {
+
+    final static int LENGTH = 2;
+
+    private static final int ARP_OPCODE_VAL_REQUEST   = 1;
+    private static final int ARP_OPCODE_VAL_REPLY = 2;
+    private static final int ARP_OPCODE_VAL_REQUEST_REVERSE   = 3;
+    private static final int ARP_OPCODE_VAL_REPLY_REVERSE = 4;
+    private static final int ARP_OPCODE_VAL_DRARP_REQUEST = 5;
+    private static final int ARP_OPCODE_VAL_DRARP_REPLY   = 6;
+    private static final int ARP_OPCODE_VAL_DRARP_ERROR   = 7;
+    private static final int ARP_OPCODE_VAL_INARP_REQUEST = 8;
+    private static final int ARP_OPCODE_VAL_INARP_REPLY   = 9;
+    private static final int ARP_OPCODE_VAL_ARP_NAK   = 10;
+    private static final int ARP_OPCODE_VAL_MARS_REQUEST  = 11;
+    private static final int ARP_OPCODE_VAL_MARS_MULTI    = 12;
+    private static final int ARP_OPCODE_VAL_MARS_MSERV    = 13;
+    private static final int ARP_OPCODE_VAL_MARS_JOIN = 14;
+    private static final int ARP_OPCODE_VAL_MARS_LEAVE    = 15;
+    private static final int ARP_OPCODE_VAL_MARS_NAK  = 16;
+    private static final int ARP_OPCODE_VAL_MARS_UNSERV   = 17;
+    private static final int ARP_OPCODE_VAL_MARS_SJOIN    = 18;
+    private static final int ARP_OPCODE_VAL_MARS_SLEAVE   = 19;
+    private static final int ARP_OPCODE_VAL_MARS_GROUPLIST_REQUEST    = 20;
+    private static final int ARP_OPCODE_VAL_MARS_GROUPLIST_REPLY  = 21;
+    private static final int ARP_OPCODE_VAL_MARS_REDIRECT_MAP = 22;
+    private static final int ARP_OPCODE_VAL_MAPOS_UNARP   = 23;
+    private static final int ARP_OPCODE_VAL_OP_EXP1   = 24;
+    private static final int ARP_OPCODE_VAL_OP_EXP2   = 25;
+
+    public static ArpOpcode ARP_OPCODE_REQUEST  = new ArpOpcode(ARP_OPCODE_VAL_REQUEST);
+    public static ArpOpcode ARP_OPCODE_REPLY    = new ArpOpcode(ARP_OPCODE_VAL_REPLY);
+    public static ArpOpcode ARP_OPCODE_REQUEST_REVERSE  = new ArpOpcode(ARP_OPCODE_VAL_REQUEST_REVERSE);
+    public static ArpOpcode ARP_OPCODE_REPLY_REVERSE    = new ArpOpcode(ARP_OPCODE_VAL_REPLY_REVERSE);
+    public static ArpOpcode ARP_OPCODE_DRARP_REQUEST    = new ArpOpcode(ARP_OPCODE_VAL_DRARP_REQUEST);
+    public static ArpOpcode ARP_OPCODE_DRARP_REPLY  = new ArpOpcode(ARP_OPCODE_VAL_DRARP_REPLY);
+    public static ArpOpcode ARP_OPCODE_DRARP_ERROR  = new ArpOpcode(ARP_OPCODE_VAL_DRARP_ERROR);
+    public static ArpOpcode ARP_OPCODE_INARP_REQUEST    = new ArpOpcode(ARP_OPCODE_VAL_INARP_REQUEST);
+    public static ArpOpcode ARP_OPCODE_INARP_REPLY  = new ArpOpcode(ARP_OPCODE_VAL_INARP_REPLY);
+    public static ArpOpcode ARP_OPCODE_ARP_NAK  = new ArpOpcode(ARP_OPCODE_VAL_ARP_NAK);
+    public static ArpOpcode ARP_OPCODE_MARS_REQUEST = new ArpOpcode(ARP_OPCODE_VAL_MARS_REQUEST);
+    public static ArpOpcode ARP_OPCODE_MARS_MULTI   = new ArpOpcode(ARP_OPCODE_VAL_MARS_MULTI);
+    public static ArpOpcode ARP_OPCODE_MARS_MSERV   = new ArpOpcode(ARP_OPCODE_VAL_MARS_MSERV);
+    public static ArpOpcode ARP_OPCODE_MARS_JOIN    = new ArpOpcode(ARP_OPCODE_VAL_MARS_JOIN);
+    public static ArpOpcode ARP_OPCODE_MARS_LEAVE   = new ArpOpcode(ARP_OPCODE_VAL_MARS_LEAVE);
+    public static ArpOpcode ARP_OPCODE_MARS_NAK = new ArpOpcode(ARP_OPCODE_VAL_MARS_NAK);
+    public static ArpOpcode ARP_OPCODE_MARS_UNSERV  = new ArpOpcode(ARP_OPCODE_VAL_MARS_UNSERV);
+    public static ArpOpcode ARP_OPCODE_MARS_SJOIN   = new ArpOpcode(ARP_OPCODE_VAL_MARS_SJOIN);
+    public static ArpOpcode ARP_OPCODE_MARS_SLEAVE  = new ArpOpcode(ARP_OPCODE_VAL_MARS_SLEAVE);
+    public static ArpOpcode ARP_OPCODE_MARS_GROUPLIST_REQUEST   = new ArpOpcode(ARP_OPCODE_VAL_MARS_GROUPLIST_REQUEST);
+    public static ArpOpcode ARP_OPCODE_MARS_GROUPLIST_REPLY = new ArpOpcode(ARP_OPCODE_VAL_MARS_GROUPLIST_REPLY);
+    public static ArpOpcode ARP_OPCODE_MARS_REDIRECT_MAP    = new ArpOpcode(ARP_OPCODE_VAL_MARS_REDIRECT_MAP);
+    public static ArpOpcode ARP_OPCODE_MAPOS_UNARP  = new ArpOpcode(ARP_OPCODE_VAL_MAPOS_UNARP);
+    public static ArpOpcode ARP_OPCODE_OP_EXP1  = new ArpOpcode(ARP_OPCODE_VAL_OP_EXP1);
+    public static ArpOpcode ARP_OPCODE_OP_EXP2  = new ArpOpcode(ARP_OPCODE_VAL_OP_EXP2);
+
+    private static final int MIN_OPCODE = 0;
+    private static final int MAX_OPCODE = 0xFFFF;
+
+    private final int opcode;
+
+    private ArpOpcode(int opcode) {
+        this.opcode = opcode;
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    public int getOpcode() {
+        return this.opcode;
+    }
+
+    public static ArpOpcode of(int opcode) {
+        if (opcode < MIN_OPCODE || opcode > MAX_OPCODE)
+            throw new IllegalArgumentException("Invalid ARP opcode: " + opcode);
+        switch (opcode) {
+            case ARP_OPCODE_VAL_REQUEST:
+                return ARP_OPCODE_REQUEST;
+            case ARP_OPCODE_VAL_REPLY:
+                return ARP_OPCODE_REPLY;
+            case ARP_OPCODE_VAL_REQUEST_REVERSE:
+                return ARP_OPCODE_REQUEST_REVERSE;
+            case ARP_OPCODE_VAL_REPLY_REVERSE:
+                return ARP_OPCODE_REPLY_REVERSE;
+            case ARP_OPCODE_VAL_DRARP_REQUEST:
+                return ARP_OPCODE_DRARP_REQUEST;
+            case ARP_OPCODE_VAL_DRARP_REPLY:
+                return ARP_OPCODE_DRARP_REPLY;
+            case ARP_OPCODE_VAL_DRARP_ERROR:
+                return ARP_OPCODE_DRARP_ERROR;
+            case ARP_OPCODE_VAL_INARP_REQUEST:
+                return ARP_OPCODE_INARP_REQUEST;
+            case ARP_OPCODE_VAL_INARP_REPLY:
+                return ARP_OPCODE_INARP_REPLY;
+            case ARP_OPCODE_VAL_ARP_NAK:
+                return ARP_OPCODE_ARP_NAK;
+            case ARP_OPCODE_VAL_MARS_REQUEST:
+                return ARP_OPCODE_MARS_REQUEST;
+            case ARP_OPCODE_VAL_MARS_MULTI:
+                return ARP_OPCODE_MARS_MULTI;
+            case ARP_OPCODE_VAL_MARS_MSERV:
+                return ARP_OPCODE_MARS_MSERV;
+            case ARP_OPCODE_VAL_MARS_JOIN:
+                return ARP_OPCODE_MARS_JOIN;
+            case ARP_OPCODE_VAL_MARS_LEAVE:
+                return ARP_OPCODE_MARS_LEAVE;
+            case ARP_OPCODE_VAL_MARS_NAK:
+                return ARP_OPCODE_MARS_NAK;
+            case ARP_OPCODE_VAL_MARS_UNSERV:
+                return ARP_OPCODE_MARS_UNSERV;
+            case ARP_OPCODE_VAL_MARS_SJOIN:
+                return ARP_OPCODE_MARS_SJOIN;
+            case ARP_OPCODE_VAL_MARS_SLEAVE:
+                return ARP_OPCODE_MARS_SLEAVE;
+            case ARP_OPCODE_VAL_MARS_GROUPLIST_REQUEST:
+                return ARP_OPCODE_MARS_GROUPLIST_REQUEST;
+            case ARP_OPCODE_VAL_MARS_GROUPLIST_REPLY:
+                return ARP_OPCODE_MARS_GROUPLIST_REPLY;
+            case ARP_OPCODE_VAL_MARS_REDIRECT_MAP:
+                return ARP_OPCODE_MARS_REDIRECT_MAP;
+            case ARP_OPCODE_VAL_MAPOS_UNARP:
+                return ARP_OPCODE_MAPOS_UNARP;
+            case ARP_OPCODE_VAL_OP_EXP1:
+                return ARP_OPCODE_OP_EXP1;
+            case ARP_OPCODE_VAL_OP_EXP2:
+                return ARP_OPCODE_OP_EXP2;
+            default:
+                return new ArpOpcode(opcode);
+        }
+    }
+    
+    public void write2Bytes(ChannelBuffer c) {
+        c.writeShort(this.opcode);
+    }
+    
+    public static ArpOpcode read2Bytes(ChannelBuffer c) {
+        return ArpOpcode.of(c.readUnsignedShort());
+    }
+}
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java b/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java
index b86a38f..f0f0a2c 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java
@@ -1,7 +1,7 @@
 package org.openflow.types;
 
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
+
 
 /**
  * EtherType field representation.
@@ -110,23 +110,6 @@
         return LENGTH;
     }
 
-    volatile byte[] bytesCache = null;
-
-    @Override
-    public byte[] getBytes() {
-        if (bytesCache == null) {
-            synchronized (this) {
-                if (bytesCache == null) {
-                    bytesCache = new byte[] {
-                                             (byte) ((rawValue >>> 8) & 0xFF),
-                                             (byte) ((rawValue >>> 0) & 0xFF)
-                    };
-                }
-            }
-        }
-        return bytesCache;
-    }
-
     public static EthType of(int type) {
         switch (type) {
             case ETH_TYPE_VAL_IPv4:
@@ -243,24 +226,13 @@
     public String toString() {
         return Integer.toHexString(rawValue);
     }
-
-    public static final Serializer<EthType> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<EthType> SERIALIZER_V11 = SERIALIZER_V10;
-    public static final Serializer<EthType> SERIALIZER_V12 = SERIALIZER_V10;
-    public static final Serializer<EthType> SERIALIZER_V13 = SERIALIZER_V10;
-
-    private static class SerializerV10 implements OFValueType.Serializer<EthType> {
-
-        @Override
-        public void writeTo(EthType value, ChannelBuffer c) {
-            c.writeShort(value.rawValue);
-        }
-
-        @Override
-        public EthType readFrom(ChannelBuffer c) throws OFParseError {
-            return EthType.of(c.readUnsignedShort());
-        }
-
+    
+    public void write2Bytes(ChannelBuffer c) {
+        c.writeShort(this.rawValue);
+    }
+    
+    public static EthType read2Bytes(ChannelBuffer c) {
+        return EthType.of(c.readUnsignedShort());
     }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Code.java b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Code.java
new file mode 100644
index 0000000..147b5f7
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Code.java
@@ -0,0 +1,44 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * 
+ * @author Yotam Harchol (yotam.harchol@bigswitch.com)
+ *
+ */
+public class ICMPv4Code implements OFValueType {
+
+    final static int LENGTH = 1;
+    final static short MAX_CODE = 0xFF;
+
+    private final short code;
+
+    private ICMPv4Code(short code) {
+        this.code = code;
+    }
+
+    public static ICMPv4Code of(short code) {
+        if (code > MAX_CODE || code < 0)
+            throw new IllegalArgumentException("Illegal ICMPv4 code: " + code);
+        return new ICMPv4Code(code);
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+    
+    public short getCode() {
+        return code;
+    }
+    
+    public void writeByte(ChannelBuffer c) {
+        c.writeByte(this.code);
+    }
+    
+    public static ICMPv4Code readByte(ChannelBuffer c) {
+        return ICMPv4Code.of(c.readUnsignedByte());
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Type.java b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Type.java
new file mode 100644
index 0000000..01d6e8f
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Type.java
@@ -0,0 +1,158 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class ICMPv4Type implements OFValueType {
+
+    final static int LENGTH = 1;
+
+    private static final short ICMPV4_TYPE_VAL_ECHO_REPLY    = 0;
+    private static final short ICMPV4_TYPE_VAL_DESTINATION_UNREACHABLE   = 3;
+    private static final short ICMPV4_TYPE_VAL_SOURCE_QUENCH = 4;
+    private static final short ICMPV4_TYPE_VAL_REDIRECT  = 5;
+    private static final short ICMPV4_TYPE_VAL_ALTERNATE_HOST_ADDRESS    = 6;
+    private static final short ICMPV4_TYPE_VAL_ECHO  = 8;
+    private static final short ICMPV4_TYPE_VAL_ROUTER_ADVERTISEMENT  = 9;
+    private static final short ICMPV4_TYPE_VAL_ROUTER_SOLICITATION   = 10;
+    private static final short ICMPV4_TYPE_VAL_TIME_EXCEEDED = 11;
+    private static final short ICMPV4_TYPE_VAL_PARAMETER_PROBLEM = 12;
+    private static final short ICMPV4_TYPE_VAL_TIMESTAMP = 13;
+    private static final short ICMPV4_TYPE_VAL_TIMESTAMP_REPLY   = 14;
+    private static final short ICMPV4_TYPE_VAL_INFORMATION_REQUEST   = 15;
+    private static final short ICMPV4_TYPE_VAL_INFORMATION_REPLY = 16;
+    private static final short ICMPV4_TYPE_VAL_ADDRESS_MASK_REQUEST  = 17;
+    private static final short ICMPV4_TYPE_VAL_ADDRESS_MASK_REPLY    = 18;
+    private static final short ICMPV4_TYPE_VAL_TRACEROUTE    = 30;
+    private static final short ICMPV4_TYPE_VAL_DATAGRAM_CONVERSION_ERROR = 31;
+    private static final short ICMPV4_TYPE_VAL_MOBILE_HOST_REDIRECT  = 32;
+    private static final short ICMPV4_TYPE_VAL_IPV6_WHERE_ARE_YOU    = 33;
+    private static final short ICMPV4_TYPE_VAL_IPV6_I_AM_HERE    = 34;
+    private static final short ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REQUEST   = 35;
+    private static final short ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REPLY = 36;
+    private static final short ICMPV4_TYPE_VAL_DOMAIN_NAME_REQUEST   = 37;
+    private static final short ICMPV4_TYPE_VAL_DOMAIN_NAME_REPLY = 38;
+    private static final short ICMPV4_TYPE_VAL_SKIP  = 39;
+    private static final short ICMPV4_TYPE_VAL_PHOTURIS  = 40;
+    private static final short ICMPV4_TYPE_VAL_EXPERIMENTAL_MOBILITY = 41;
+
+    public static final ICMPv4Type ICMPV4_TYPE_ECHO_REPLY   = new ICMPv4Type(ICMPV4_TYPE_VAL_ECHO_REPLY);
+    public static final ICMPv4Type ICMPV4_TYPE_DESTINATION_UNREACHABLE  = new ICMPv4Type(ICMPV4_TYPE_VAL_DESTINATION_UNREACHABLE);
+    public static final ICMPv4Type ICMPV4_TYPE_SOURCE_QUENCH    = new ICMPv4Type(ICMPV4_TYPE_VAL_SOURCE_QUENCH);
+    public static final ICMPv4Type ICMPV4_TYPE_REDIRECT = new ICMPv4Type(ICMPV4_TYPE_VAL_REDIRECT);
+    public static final ICMPv4Type ICMPV4_TYPE_ALTERNATE_HOST_ADDRESS   = new ICMPv4Type(ICMPV4_TYPE_VAL_ALTERNATE_HOST_ADDRESS);
+    public static final ICMPv4Type ICMPV4_TYPE_ECHO = new ICMPv4Type(ICMPV4_TYPE_VAL_ECHO);
+    public static final ICMPv4Type ICMPV4_TYPE_ROUTER_ADVERTISEMENT = new ICMPv4Type(ICMPV4_TYPE_VAL_ROUTER_ADVERTISEMENT);
+    public static final ICMPv4Type ICMPV4_TYPE_ROUTER_SOLICITATION  = new ICMPv4Type(ICMPV4_TYPE_VAL_ROUTER_SOLICITATION);
+    public static final ICMPv4Type ICMPV4_TYPE_TIME_EXCEEDED    = new ICMPv4Type(ICMPV4_TYPE_VAL_TIME_EXCEEDED);
+    public static final ICMPv4Type ICMPV4_TYPE_PARAMETER_PROBLEM    = new ICMPv4Type(ICMPV4_TYPE_VAL_PARAMETER_PROBLEM);
+    public static final ICMPv4Type ICMPV4_TYPE_TIMESTAMP    = new ICMPv4Type(ICMPV4_TYPE_VAL_TIMESTAMP);
+    public static final ICMPv4Type ICMPV4_TYPE_TIMESTAMP_REPLY  = new ICMPv4Type(ICMPV4_TYPE_VAL_TIMESTAMP_REPLY);
+    public static final ICMPv4Type ICMPV4_TYPE_INFORMATION_REQUEST  = new ICMPv4Type(ICMPV4_TYPE_VAL_INFORMATION_REQUEST);
+    public static final ICMPv4Type ICMPV4_TYPE_INFORMATION_REPLY    = new ICMPv4Type(ICMPV4_TYPE_VAL_INFORMATION_REPLY);
+    public static final ICMPv4Type ICMPV4_TYPE_ADDRESS_MASK_REQUEST = new ICMPv4Type(ICMPV4_TYPE_VAL_ADDRESS_MASK_REQUEST);
+    public static final ICMPv4Type ICMPV4_TYPE_ADDRESS_MASK_REPLY   = new ICMPv4Type(ICMPV4_TYPE_VAL_ADDRESS_MASK_REPLY);
+    public static final ICMPv4Type ICMPV4_TYPE_TRACEROUTE   = new ICMPv4Type(ICMPV4_TYPE_VAL_TRACEROUTE);
+    public static final ICMPv4Type ICMPV4_TYPE_DATAGRAM_CONVERSION_ERROR    = new ICMPv4Type(ICMPV4_TYPE_VAL_DATAGRAM_CONVERSION_ERROR);
+    public static final ICMPv4Type ICMPV4_TYPE_MOBILE_HOST_REDIRECT = new ICMPv4Type(ICMPV4_TYPE_VAL_MOBILE_HOST_REDIRECT);
+    public static final ICMPv4Type ICMPV4_TYPE_IPV6_WHERE_ARE_YOU  = new ICMPv4Type(ICMPV4_TYPE_VAL_IPV6_WHERE_ARE_YOU);
+    public static final ICMPv4Type ICMPV4_TYPE_IPV6_I_AM_HERE = new ICMPv4Type(ICMPV4_TYPE_VAL_IPV6_I_AM_HERE);
+    public static final ICMPv4Type ICMPV4_TYPE_MOBILE_REGISTRATION_REQUEST  = new ICMPv4Type(ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REQUEST);
+    public static final ICMPv4Type ICMPV4_TYPE_MOBILE_REGISTRATION_REPLY    = new ICMPv4Type(ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REPLY);
+    public static final ICMPv4Type ICMPV4_TYPE_DOMAIN_NAME_REQUEST  = new ICMPv4Type(ICMPV4_TYPE_VAL_DOMAIN_NAME_REQUEST);
+    public static final ICMPv4Type ICMPV4_TYPE_DOMAIN_NAME_REPLY    = new ICMPv4Type(ICMPV4_TYPE_VAL_DOMAIN_NAME_REPLY);
+    public static final ICMPv4Type ICMPV4_TYPE_SKIP = new ICMPv4Type(ICMPV4_TYPE_VAL_SKIP);
+    public static final ICMPv4Type ICMPV4_TYPE_PHOTURIS = new ICMPv4Type(ICMPV4_TYPE_VAL_PHOTURIS);
+    public static final ICMPv4Type ICMPV4_TYPE_EXPERIMENTAL_MOBILITY    = new ICMPv4Type(ICMPV4_TYPE_VAL_EXPERIMENTAL_MOBILITY);
+
+    private final short type;
+    
+    private static final int MIN_TYPE = 0;
+    private static final int MAX_TYPE = 0xFF;    
+
+    private ICMPv4Type(short type) {
+        this.type = type;
+    }
+
+    public static ICMPv4Type of(short type) {
+        if (type < MIN_TYPE || type > MAX_TYPE)
+            throw new IllegalArgumentException("Invalid ICMPv4 type: " + type);
+        switch (type) {
+            case ICMPV4_TYPE_VAL_ECHO_REPLY:
+                return ICMPV4_TYPE_ECHO_REPLY;
+            case ICMPV4_TYPE_VAL_DESTINATION_UNREACHABLE:
+                return ICMPV4_TYPE_DESTINATION_UNREACHABLE;
+            case ICMPV4_TYPE_VAL_SOURCE_QUENCH:
+                return ICMPV4_TYPE_SOURCE_QUENCH;
+            case ICMPV4_TYPE_VAL_REDIRECT:
+                return ICMPV4_TYPE_REDIRECT;
+            case ICMPV4_TYPE_VAL_ALTERNATE_HOST_ADDRESS:
+                return ICMPV4_TYPE_ALTERNATE_HOST_ADDRESS;
+            case ICMPV4_TYPE_VAL_ECHO:
+                return ICMPV4_TYPE_ECHO;
+            case ICMPV4_TYPE_VAL_ROUTER_ADVERTISEMENT:
+                return ICMPV4_TYPE_ROUTER_ADVERTISEMENT;
+            case ICMPV4_TYPE_VAL_ROUTER_SOLICITATION:
+                return ICMPV4_TYPE_ROUTER_SOLICITATION;
+            case ICMPV4_TYPE_VAL_TIME_EXCEEDED:
+                return ICMPV4_TYPE_TIME_EXCEEDED;
+            case ICMPV4_TYPE_VAL_PARAMETER_PROBLEM:
+                return ICMPV4_TYPE_PARAMETER_PROBLEM;
+            case ICMPV4_TYPE_VAL_TIMESTAMP:
+                return ICMPV4_TYPE_TIMESTAMP;
+            case ICMPV4_TYPE_VAL_TIMESTAMP_REPLY:
+                return ICMPV4_TYPE_TIMESTAMP_REPLY;
+            case ICMPV4_TYPE_VAL_INFORMATION_REQUEST:
+                return ICMPV4_TYPE_INFORMATION_REQUEST;
+            case ICMPV4_TYPE_VAL_INFORMATION_REPLY:
+                return ICMPV4_TYPE_INFORMATION_REPLY;
+            case ICMPV4_TYPE_VAL_ADDRESS_MASK_REQUEST:
+                return ICMPV4_TYPE_ADDRESS_MASK_REQUEST;
+            case ICMPV4_TYPE_VAL_ADDRESS_MASK_REPLY:
+                return ICMPV4_TYPE_ADDRESS_MASK_REPLY;
+            case ICMPV4_TYPE_VAL_TRACEROUTE:
+                return ICMPV4_TYPE_TRACEROUTE;
+            case ICMPV4_TYPE_VAL_DATAGRAM_CONVERSION_ERROR:
+                return ICMPV4_TYPE_DATAGRAM_CONVERSION_ERROR;
+            case ICMPV4_TYPE_VAL_MOBILE_HOST_REDIRECT:
+                return ICMPV4_TYPE_MOBILE_HOST_REDIRECT;
+            case ICMPV4_TYPE_VAL_IPV6_WHERE_ARE_YOU:
+                return ICMPV4_TYPE_IPV6_WHERE_ARE_YOU;
+            case ICMPV4_TYPE_VAL_IPV6_I_AM_HERE:
+                return ICMPV4_TYPE_IPV6_I_AM_HERE;
+            case ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REQUEST:
+                return ICMPV4_TYPE_MOBILE_REGISTRATION_REQUEST;
+            case ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REPLY:
+                return ICMPV4_TYPE_MOBILE_REGISTRATION_REPLY;
+            case ICMPV4_TYPE_VAL_DOMAIN_NAME_REQUEST:
+                return ICMPV4_TYPE_DOMAIN_NAME_REQUEST;
+            case ICMPV4_TYPE_VAL_DOMAIN_NAME_REPLY:
+                return ICMPV4_TYPE_DOMAIN_NAME_REPLY;
+            case ICMPV4_TYPE_VAL_SKIP:
+                return ICMPV4_TYPE_SKIP;
+            case ICMPV4_TYPE_VAL_PHOTURIS:
+                return ICMPV4_TYPE_PHOTURIS;
+            case ICMPV4_TYPE_VAL_EXPERIMENTAL_MOBILITY:
+                return ICMPV4_TYPE_EXPERIMENTAL_MOBILITY;
+            default:
+                return new ICMPv4Type(type);
+        }
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+    
+    public short getType() {
+        return type;
+    }
+    
+    public void writeByte(ChannelBuffer c) {
+        c.writeByte(this.type);
+    }
+    
+    public static ICMPv4Type readByte(ChannelBuffer c) {
+        return ICMPv4Type.of(c.readUnsignedByte());
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
index c05a7e3..78b8dd2 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
@@ -1,7 +1,7 @@
 package org.openflow.types;
 
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
+
 
 
 /**
@@ -56,61 +56,6 @@
         }
         return IPv4.of(raw);
     }
-    
-    public static OFValueType ofPossiblyMasked(final String string) {
-        int start = 0;
-        int shift = 24;
-        int slashPos;
-
-        String ip = string;
-        int maskBits = 0;
-        if ((slashPos = string.indexOf('/')) != -1) {
-            ip = string.substring(0, slashPos);
-            try {
-                String suffix = string.substring(slashPos + 1);
-                if (suffix.length() == 0)
-                    throw new IllegalArgumentException("IP Address not well formed: " + string);
-                maskBits = 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);
-            }
-        }
-        
-        int raw = 0;
-        while (shift >= 0) {
-            int end = ip.indexOf('.', start);
-            if (end == start || !((shift > 0) ^ (end < 0)))
-                throw new IllegalArgumentException("IP Address not well formed: " + string);
-
-            String substr =
-                    end > 0 ? ip.substring(start, end) : ip.substring(start);
-            int val;
-            try {
-                val = Integer.parseInt(substr);
-            } catch (NumberFormatException e) {
-                throw new IllegalArgumentException("IP Address not well formed: " + string);
-            }
-            if (val < 0 || val > 255)
-                throw new IllegalArgumentException("IP Address not well formed: " + string);
-
-            raw |= val << shift;
-
-            shift -= 8;
-            start = end + 1;
-        }
-        
-        if (maskBits == 0) {
-            // No mask
-            return IPv4.of(raw);
-        } else {
-            // With mask
-            int mask = (-1) << (32 - maskBits);
-            return Masked.<IPv4>of(IPv4.of(raw), IPv4.of(mask));
-        }
-    }
 
     public int getInt() {
         return rawValue;
@@ -170,22 +115,12 @@
         return true;
     }
     
-    public static final Serializer<IPv4> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<IPv4> SERIALIZER_V11 = SERIALIZER_V10;
-    public static final Serializer<IPv4> SERIALIZER_V12 = SERIALIZER_V10;
-    public static final Serializer<IPv4> SERIALIZER_V13 = SERIALIZER_V10;
-    
-    private static class SerializerV10 implements OFValueType.Serializer<IPv4> {
-
-        @Override
-        public void writeTo(IPv4 value, ChannelBuffer c) {
-            c.writeInt(value.rawValue);
-        }
-
-        @Override
-        public IPv4 readFrom(ChannelBuffer c) throws OFParseError {
-            return IPv4.of(c.readInt());
-        }
-        
+    public void write4Bytes(ChannelBuffer c) {
+        c.writeInt(rawValue);
     }
+    
+    public static IPv4 read4Bytes(ChannelBuffer c) {
+        return IPv4.of(c.readInt());
+    }
+    
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java
new file mode 100644
index 0000000..afb89ed
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java
@@ -0,0 +1,83 @@
+package org.openflow.types;
+
+public class IPv4WithMask extends Masked<IPv4> {
+
+    private IPv4WithMask(int rawValue, int rawMask) {
+        super(IPv4.of(rawValue), IPv4.of(rawMask));
+    }
+    
+    private IPv4WithMask(IPv4 value, IPv4 mask) {
+        super(value, mask);
+    }
+    
+    public static IPv4WithMask of(int rawValue, int rawMask) {
+        return new IPv4WithMask(rawValue, rawMask);
+    }
+    
+    public static IPv4WithMask of(IPv4 value, IPv4 mask) {
+        return new IPv4WithMask(value, mask);
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder();
+        res.append(((IPv4)value).toString());
+        
+        int maskint = ((IPv4)mask).getInt();
+        res.append('/');
+        if (Integer.bitCount((~maskint) + 1) == 1) {
+            // CIDR notation
+            res.append(Integer.bitCount(maskint));
+        } else {
+            // Full address mask
+            res.append(((IPv4)mask).toString());
+        }
+        
+        return res.toString();
+    }
+    
+    public static OFValueType ofPossiblyMasked(final String string) {
+        int slashPos;
+        String ip = string;
+        int maskBits = 0;
+        IPv4 maskAddress = null;
+
+        // Read mask suffix
+        if ((slashPos = string.indexOf('/')) != -1) {
+            ip = string.substring(0, slashPos);
+            try {
+                String suffix = string.substring(slashPos + 1);
+                if (suffix.length() == 0)
+                    throw new IllegalArgumentException("IP Address not well formed: " + string);
+                if (suffix.indexOf('.') != -1) {
+                    // Full mask
+                    maskAddress = IPv4.of(suffix);
+                } else {
+                    // CIDR Suffix
+                    maskBits = 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
+        IPv4 ipv4 = IPv4.of(ip);
+        
+        if (maskAddress != null) {
+            // Full address mask
+            return IPv4WithMask.of(ipv4, maskAddress);
+        } else if (maskBits == 0) {
+            // No mask
+            return ipv4;
+        } else {
+            // With mask
+            int mask = (-1) << (32 - maskBits);
+            return IPv4WithMask.of(ipv4, IPv4.of(mask));
+        }
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
index ff5e9ed..e3166fd 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
@@ -270,24 +270,12 @@
         return true;
     }
     
-    public static final Serializer<IPv6> SERIALIZER_V12 = new SerializerV12();
-    public static final Serializer<IPv6> SERIALIZER_V13 = SERIALIZER_V12;
-    
-    private static class SerializerV12 implements OFValueType.Serializer<IPv6> {
-
-        @Override
-        public void writeTo(IPv6 value, ChannelBuffer c) {
-            c.writeLong(value.raw1);
-            c.writeLong(value.raw2);            
-        }
-
-        @Override
-        public IPv6 readFrom(ChannelBuffer c) throws OFParseError {
-            return IPv6.of(c.readLong(), c.readLong());
-        }
-        
+    public void write16Bytes(ChannelBuffer c) {
+        c.writeLong(this.raw1);
+        c.writeLong(this.raw2);            
     }
-    
-    
 
+    public static IPv6 read16Bytes(ChannelBuffer c) throws OFParseError {
+        return IPv6.of(c.readLong(), c.readLong());
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6FlowLabel.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6FlowLabel.java
new file mode 100644
index 0000000..6d9bfb5
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6FlowLabel.java
@@ -0,0 +1,56 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+
+public class IPv6FlowLabel implements OFValueType {
+
+    static final int LENGTH = 4;
+    
+    private final int label;
+    
+    private IPv6FlowLabel(int label) {
+        this.label = label;
+    }
+    
+    public static IPv6FlowLabel of(int label) {
+        return new IPv6FlowLabel(label);
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof IPv6FlowLabel))
+            return false;
+        IPv6FlowLabel other = (IPv6FlowLabel)obj;
+        if (other.label != this.label)
+            return false;
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 59;
+        int result = 1;
+        result = prime * result + label;
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return Integer.toHexString(label);
+    }
+
+    public void write4Bytes(ChannelBuffer c) {
+        c.writeInt(this.label);
+    }
+
+    public static IPv6FlowLabel read4Bytes(ChannelBuffer c) throws OFParseError {
+        return IPv6FlowLabel.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java
new file mode 100644
index 0000000..f809d67
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java
@@ -0,0 +1,91 @@
+package org.openflow.types;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+
+public class IPv6WithMask extends Masked<IPv6> {
+
+    private IPv6WithMask(IPv6 value, IPv6 mask) {
+        super(value, mask);
+    }
+    
+    public static IPv6WithMask of(IPv6 value, IPv6 mask) {
+        return new IPv6WithMask(value, mask);
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder();
+        res.append(((IPv6)value).toString());
+        res.append('/');
+        
+        BigInteger maskint = new BigInteger(((IPv6)mask).getBytes());
+        if (maskint.not().add(BigInteger.ONE).bitCount() == 1) {
+            // CIDR notation
+            res.append(maskint.bitCount());
+        } else {
+            // Full address mask
+            res.append(((IPv6)mask).toString());
+        }
+        
+        return res.toString();
+    }
+    
+    public static OFValueType ofPossiblyMasked(final String string) {
+        int slashPos;
+        String ip = string;
+        int maskBits = 0;
+        IPv6 maskAddress = null;
+
+        // Read mask suffix
+        if ((slashPos = string.indexOf('/')) != -1) {
+            ip = string.substring(0, slashPos);
+            try {
+                String suffix = string.substring(slashPos + 1);
+                if (suffix.length() == 0)
+                    throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
+                if (suffix.indexOf(':') != -1) {
+                    // Full mask
+                    maskAddress = IPv6.of(suffix);
+                } else {
+                    // CIDR Suffix
+                    maskBits = 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
+        IPv6 ipv6 = IPv6.of(ip);
+        
+        if (maskAddress != null) {
+            // Full address mask
+            return IPv6WithMask.of(ipv6, maskAddress);
+        } else if (maskBits == 0) {
+            // No mask
+            return ipv6;
+        } 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 IPv6WithMask.of(ipv6, IPv6.of(maskBytes));
+        }
+    }
+
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IpDscp.java b/java_gen/pre-written/src/main/java/org/openflow/types/IpDscp.java
new file mode 100644
index 0000000..033e574
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IpDscp.java
@@ -0,0 +1,233 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+
+public enum IpDscp implements OFValueType {
+    DSCP_0((byte)0),
+    DSCP_1((byte)1),
+    DSCP_2((byte)2),
+    DSCP_3((byte)3),
+    DSCP_4((byte)4),
+    DSCP_5((byte)5),
+    DSCP_6((byte)6),
+    DSCP_7((byte)7),
+    DSCP_8((byte)8),
+    DSCP_9((byte)9),
+    DSCP_10((byte)10),
+    DSCP_11((byte)11),
+    DSCP_12((byte)12),
+    DSCP_13((byte)13),
+    DSCP_14((byte)14),
+    DSCP_15((byte)15),
+    DSCP_16((byte)16),
+    DSCP_17((byte)17),
+    DSCP_18((byte)18),
+    DSCP_19((byte)19),
+    DSCP_20((byte)20),
+    DSCP_21((byte)21),
+    DSCP_22((byte)22),
+    DSCP_23((byte)23),
+    DSCP_24((byte)24),
+    DSCP_25((byte)25),
+    DSCP_26((byte)26),
+    DSCP_27((byte)27),
+    DSCP_28((byte)28),
+    DSCP_29((byte)29),
+    DSCP_30((byte)30),
+    DSCP_31((byte)31),
+    DSCP_32((byte)32),
+    DSCP_33((byte)33),
+    DSCP_34((byte)34),
+    DSCP_35((byte)35),
+    DSCP_36((byte)36),
+    DSCP_37((byte)37),
+    DSCP_38((byte)38),
+    DSCP_39((byte)39),
+    DSCP_40((byte)40),
+    DSCP_41((byte)41),
+    DSCP_42((byte)42),
+    DSCP_43((byte)43),
+    DSCP_44((byte)44),
+    DSCP_45((byte)45),
+    DSCP_46((byte)46),
+    DSCP_47((byte)47),
+    DSCP_48((byte)48),
+    DSCP_49((byte)49),
+    DSCP_50((byte)50),
+    DSCP_51((byte)51),
+    DSCP_52((byte)52),
+    DSCP_53((byte)53),
+    DSCP_54((byte)54),
+    DSCP_55((byte)55),
+    DSCP_56((byte)56),
+    DSCP_57((byte)57),
+    DSCP_58((byte)58),
+    DSCP_59((byte)59),
+    DSCP_60((byte)60),
+    DSCP_61((byte)61),
+    DSCP_62((byte)62),
+    DSCP_63((byte)63);
+    
+    static final int LENGTH = 1;
+    
+    private final byte dscp;
+    
+    private IpDscp(byte dscp) {
+        this.dscp = dscp;
+    }
+    
+    public static IpDscp of(byte dscp) {
+        switch (dscp) {
+            case 0:
+                return DSCP_0;
+            case 1:
+                return DSCP_1;
+            case 2:
+                return DSCP_2;
+            case 3:
+                return DSCP_3;
+            case 4:
+                return DSCP_4;
+            case 5:
+                return DSCP_5;
+            case 6:
+                return DSCP_6;
+            case 7:
+                return DSCP_7;
+            case 8:
+                return DSCP_8;
+            case 9:
+                return DSCP_9;
+            case 10:
+                return DSCP_10;
+            case 11:
+                return DSCP_11;
+            case 12:
+                return DSCP_12;
+            case 13:
+                return DSCP_13;
+            case 14:
+                return DSCP_14;
+            case 15:
+                return DSCP_15;
+            case 16:
+                return DSCP_16;
+            case 17:
+                return DSCP_17;
+            case 18:
+                return DSCP_18;
+            case 19:
+                return DSCP_19;
+            case 20:
+                return DSCP_20;
+            case 21:
+                return DSCP_21;
+            case 22:
+                return DSCP_22;
+            case 23:
+                return DSCP_23;
+            case 24:
+                return DSCP_24;
+            case 25:
+                return DSCP_25;
+            case 26:
+                return DSCP_26;
+            case 27:
+                return DSCP_27;
+            case 28:
+                return DSCP_28;
+            case 29:
+                return DSCP_29;
+            case 30:
+                return DSCP_30;
+            case 31:
+                return DSCP_31;
+            case 32:
+                return DSCP_32;
+            case 33:
+                return DSCP_33;
+            case 34:
+                return DSCP_34;
+            case 35:
+                return DSCP_35;
+            case 36:
+                return DSCP_36;
+            case 37:
+                return DSCP_37;
+            case 38:
+                return DSCP_38;
+            case 39:
+                return DSCP_39;
+            case 40:
+                return DSCP_40;
+            case 41:
+                return DSCP_41;
+            case 42:
+                return DSCP_42;
+            case 43:
+                return DSCP_43;
+            case 44:
+                return DSCP_44;
+            case 45:
+                return DSCP_45;
+            case 46:
+                return DSCP_46;
+            case 47:
+                return DSCP_47;
+            case 48:
+                return DSCP_48;
+            case 49:
+                return DSCP_49;
+            case 50:
+                return DSCP_50;
+            case 51:
+                return DSCP_51;
+            case 52:
+                return DSCP_52;
+            case 53:
+                return DSCP_53;
+            case 54:
+                return DSCP_54;
+            case 55:
+                return DSCP_55;
+            case 56:
+                return DSCP_56;
+            case 57:
+                return DSCP_57;
+            case 58:
+                return DSCP_58;
+            case 59:
+                return DSCP_59;
+            case 60:
+                return DSCP_60;
+            case 61:
+                return DSCP_61;
+            case 62:
+                return DSCP_62;
+            case 63:
+                return DSCP_63;
+            default:
+                throw new IllegalArgumentException("Illegal IPv4 DSCP value: " + dscp);
+        }
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public String toString() {
+        return Integer.toHexString(dscp);
+    }
+
+    public void writeByte(ChannelBuffer c) {
+        c.writeByte(this.dscp);
+    }
+
+    public static IpDscp readByte(ChannelBuffer c) throws OFParseError {
+        return IpDscp.of((byte)(c.readUnsignedByte()));
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IpEcn.java b/java_gen/pre-written/src/main/java/org/openflow/types/IpEcn.java
new file mode 100644
index 0000000..b261d41
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IpEcn.java
@@ -0,0 +1,53 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+
+public enum IpEcn implements OFValueType {
+    ECN_00((byte)0),
+    ECN_01((byte)1),
+    ECN_10((byte)2),
+    ECN_11((byte)3);
+    
+    static final int LENGTH = 1;
+    
+    private final byte ecn;
+    
+    private IpEcn(byte ecn) {
+        this.ecn = ecn;
+    }
+    
+    public static IpEcn of(byte ecn) {
+        switch (ecn) {
+            case 0:
+                return ECN_00;
+            case 1:
+                return ECN_01;
+            case 2:
+                return ECN_10;
+            case 3:
+                return ECN_11;
+            default:
+                throw new IllegalArgumentException("Illegal IP ECN value: " + ecn);
+        }
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public String toString() {
+        return (ecn < 3 ? "0" : "") + Integer.toBinaryString(ecn);
+    }
+
+    public void writeByte(ChannelBuffer c) {
+        c.writeByte(this.ecn);
+    }
+
+    public static IpEcn readByte(ChannelBuffer c) throws OFParseError {
+        return IpEcn.of((byte)(c.readUnsignedByte()));
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java b/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java
index fc28370..436db1d 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java
@@ -1,7 +1,6 @@
 package org.openflow.types;
 
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
 
 /**
  * IP-Protocol field representation
@@ -309,20 +308,6 @@
         return LENGTH;
     }
 
-    volatile byte[] bytesCache = null;
-
-    @Override
-    public byte[] getBytes() {
-        if (bytesCache == null) {
-            synchronized (this) {
-                if (bytesCache == null) {
-                    bytesCache = new byte[] { (byte)proto };
-                }
-            }
-        }
-        return bytesCache;
-    }
-
     public static IpProtocol of(short proto) {
         switch (proto) {
             case IP_PROTO_NUM_HOPOPT:
@@ -639,24 +624,12 @@
     public String toString() {
         return Integer.toHexString(proto);
     }
-
-    public static final Serializer<IpProtocol> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<IpProtocol> SERIALIZER_V11 = SERIALIZER_V10;
-    public static final Serializer<IpProtocol> SERIALIZER_V12 = SERIALIZER_V10;
-    public static final Serializer<IpProtocol> SERIALIZER_V13 = SERIALIZER_V10;
-
-    private static class SerializerV10 implements OFValueType.Serializer<IpProtocol> {
-
-        @Override
-        public void writeTo(IpProtocol value, ChannelBuffer c) {
-            c.writeByte(value.proto);
-        }
-
-        @Override
-        public IpProtocol readFrom(ChannelBuffer c) throws OFParseError {
-            return IpProtocol.of((short)(c.readUnsignedByte() & 0x00FF));
-        }
-
+    
+    public void writeByte(ChannelBuffer c) {
+        c.writeByte(this.proto);
     }
 
+    public static IpProtocol readByte(ChannelBuffer c) {
+        return IpProtocol.of(c.readUnsignedByte());
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
index ec15f74..a18dff3 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
@@ -107,28 +107,15 @@
         return rawValue;
     }
 
-    public static final Serializer<MacAddress> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<MacAddress> SERIALIZER_V11 = SERIALIZER_V10;
-    public static final Serializer<MacAddress> SERIALIZER_V12 = SERIALIZER_V10;
-    public static final Serializer<MacAddress> SERIALIZER_V13 = SERIALIZER_V10;
-
-    private static class SerializerV10 implements OFValueType.Serializer<MacAddress> {
-
-        @Override
-        public void writeTo(MacAddress value, ChannelBuffer c) {
-            c.writeInt((int) (value.rawValue >> 16));
-            c.writeShort((int) value.rawValue & 0xFFFF);
-        }
-
-        @Override
-        public MacAddress readFrom(ChannelBuffer c) throws OFParseError {
-            long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort();
-            return MacAddress.of(raw);
-        }
-        
-        
+    public void write6Bytes(ChannelBuffer c) {
+        c.writeInt((int) (this.rawValue >> 16));
+        c.writeShort((int) this.rawValue & 0xFFFF);
     }
 
+    public static MacAddress read6Bytes(ChannelBuffer c) throws OFParseError {
+        long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort();
+        return MacAddress.of(raw);
+    }
     
     
 
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java b/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java
index de6b604..011bae8 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java
@@ -3,10 +3,10 @@
 
 
 public class Masked<T extends OFValueType> implements OFValueType {
-    private T value;
-    private T mask;
+    protected T value;
+    protected T mask;
     
-    private Masked(T value, T mask) {
+    protected Masked(T value, T mask) {
         this.value = value;
         this.mask = mask;
     }
@@ -23,28 +23,6 @@
     public int getLength() {
         return this.value.getLength() + this.mask.getLength();
     }
-
-    volatile byte[] bytesCache = null;
-    
-    @Override
-    public byte[] getBytes() {
-        if (bytesCache == null) {
-            synchronized(this) {
-                if (bytesCache == null) {
-                    byte[] bytesValue = this.value.getBytes();
-                    byte[] bytesMask = this.mask.getBytes();
-                    bytesCache = new byte[bytesValue.length + bytesMask.length];
-                    System.arraycopy(bytesValue, 0, bytesCache, 0, bytesValue.length);
-                    System.arraycopy(bytesMask, 0, bytesCache, bytesValue.length, bytesMask.length);
-                }
-            }
-        }
-        return bytesCache;
-    }
-
-    public static <T extends OFValueType> Masked<T> of(T value, T mask) {
-        return new Masked<T>(value, mask);
-    }
         
     @Override
     public boolean equals(Object obj) {
@@ -65,33 +43,10 @@
 
     @Override
     public String toString() {
-        if (value.getClass() == IPv4.class) {
-            // TODO: How to output the mask when not in CIDR notation?
-            StringBuilder res = new StringBuilder();
-            res.append(((IPv4)value).toString());
-            
-            int maskint = ((IPv4)mask).getInt();
-            if (Integer.bitCount((~maskint) + 1) == 1) {
-                // CIDR notation
-                res.append('/');
-                res.append(Integer.bitCount(maskint));
-            } else {
-                // Arbitrary mask not in CIDR notation
-                // TODO: HERE?
-            }
-            
-            return res.toString();
-        } else if (value.getClass() == IPv6.class) {
-            // TODO: Return IPv6 string
-            StringBuilder sb = new StringBuilder();
-            sb.append(value.toString()).append('/').append(mask.toString());
-            return sb.toString();
-        } else {
-            // General representation: value/mask
-            StringBuilder sb = new StringBuilder();
-            sb.append(value.toString()).append('/').append(mask.toString());
-            return sb.toString();
-        }
+        // General representation: value/mask
+        StringBuilder sb = new StringBuilder();
+        sb.append(value.toString()).append('/').append(mask.toString());
+        return sb.toString();
     }
     
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java
index 9d87b8f..d8f71a3 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java
@@ -28,23 +28,6 @@
     public int getLength() {
         return LENGTH;
     }
-    
-    volatile byte[] bytesCache;
-    
-    @Override
-    public byte[] getBytes() {
-        if (bytesCache == null) {
-            synchronized (this) {
-                if (bytesCache == null) {
-                    bytesCache = new byte[] { (byte)(port & 0xFF),
-                                              (byte)((port >>> 8) & 0xFF),
-                                              (byte)((port >>> 16) & 0xFF),
-                                              (byte)((port >>> 24) & 0xFF)};
-                }
-            }
-        }
-        return bytesCache;
-    }
 
     @Override
     public boolean equals(Object obj) {
@@ -69,22 +52,12 @@
         return Integer.toHexString(port);
     }
 
-    public static final Serializer<OFPhysicalPort> SERIALIZER_V11 = new SerializerV11();
-    public static final Serializer<OFPhysicalPort> SERIALIZER_V12 = SERIALIZER_V11;
-    public static final Serializer<OFPhysicalPort> SERIALIZER_V13 = SERIALIZER_V11;
+    public void write4Bytes(ChannelBuffer c) {
+        c.writeInt(this.port);
+    }
 
-    private static class SerializerV11 implements OFValueType.Serializer<OFPhysicalPort> {
-
-        @Override
-        public void writeTo(OFPhysicalPort value, ChannelBuffer c) {
-            c.writeInt(value.port);
-        }
-
-        @Override
-        public OFPhysicalPort readFrom(ChannelBuffer c) throws OFParseError {
-            return OFPhysicalPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
-        }
-
+    public static OFPhysicalPort read4Bytes(ChannelBuffer c) throws OFParseError {
+        return OFPhysicalPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
     }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java
index 22b347d..3272660 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java
@@ -497,23 +497,6 @@
         return LENGTH;
     }
     
-    volatile byte[] bytesCache;
-    
-    @Override
-    public byte[] getBytes() {
-        if (bytesCache == null) {
-            synchronized (this) {
-                if (bytesCache == null) {
-                    bytesCache = new byte[] { (byte)(portNumber & 0xFF),
-                                              (byte)((portNumber >>> 8) & 0xFF),
-                                              (byte)((portNumber >>> 16) & 0xFF),
-                                              (byte)((portNumber >>> 24) & 0xFF) };
-                }
-            }
-        }
-        return bytesCache;
-    }
-
     @Override
     public boolean equals(Object obj) {
         if (!(obj instanceof OFPort))
@@ -532,36 +515,19 @@
         return result;
     }
 
-    public static final Serializer<OFPort> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<OFPort> SERIALIZER_V11 = new SerializerV11();
-    public static final Serializer<OFPort> SERIALIZER_V12 = SERIALIZER_V11;
-    public static final Serializer<OFPort> SERIALIZER_V13 = SERIALIZER_V11;
-
-    private static class SerializerV10 implements OFValueType.Serializer<OFPort> {
-
-        @Override
-        public void writeTo(OFPort value, ChannelBuffer c) {
-            c.writeShort(value.portNumber);
-        }
-
-        @Override
-        public OFPort readFrom(ChannelBuffer c) throws OFParseError {
-            return OFPort.of((c.readUnsignedShort() & 0x0FFFF));
-        }
-
+    public void write2Bytes(ChannelBuffer c) {
+        c.writeShort(this.portNumber);
     }
 
-    private static class SerializerV11 implements OFValueType.Serializer<OFPort> {
+    public static OFPort read2Bytes(ChannelBuffer c) throws OFParseError {
+        return OFPort.of((c.readUnsignedShort() & 0x0FFFF));
+    }
 
-        @Override
-        public void writeTo(OFPort value, ChannelBuffer c) {
-            c.writeInt(value.portNumber);
-        }
+    public void write4Bytes(ChannelBuffer c) {
+        c.writeInt(this.portNumber);
+    }
 
-        @Override
-        public OFPort readFrom(ChannelBuffer c) throws OFParseError {
-            return OFPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
-        }
-
+    public static OFPort read4Bytes(ChannelBuffer c) throws OFParseError {
+        return OFPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
     }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java
index 01e7012..51c8b36 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java
@@ -1,18 +1,10 @@
 package org.openflow.types;
 
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
 
 
 
 public interface OFValueType {
 
     public int getLength();
-    public byte[] getBytes();
-    
-    public interface Serializer<T extends OFValueType> {
-        public void writeTo(T value, ChannelBuffer c);
-        public T readFrom(ChannelBuffer c) throws OFParseError; 
-    }
-    
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java b/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
index 86ed53e..cecb349 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
@@ -31,21 +31,6 @@
     public int getLength() {
         return LENGTH;
     }
-    
-    volatile byte[] bytesCache;
-    
-    @Override
-    public byte[] getBytes() {
-        if (bytesCache == null) {
-            synchronized (this) {
-                if (bytesCache == null) {
-                    bytesCache = new byte[] { (byte)(port & 0xFF),
-                                              (byte)((port >>> 8) & 0xFF)};
-                }
-            }
-        }
-        return bytesCache;
-    }
 
     @Override
     public boolean equals(Object obj) {
@@ -70,23 +55,12 @@
         return Integer.toString(port);
     }
 
-    public static final Serializer<TransportPort> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<TransportPort> SERIALIZER_V11 = SERIALIZER_V10;
-    public static final Serializer<TransportPort> SERIALIZER_V12 = SERIALIZER_V10;
-    public static final Serializer<TransportPort> SERIALIZER_V13 = SERIALIZER_V10;
+    public void write2Bytes(ChannelBuffer c) {
+        c.writeShort(this.port);
+    }
 
-    private static class SerializerV10 implements OFValueType.Serializer<TransportPort> {
-
-        @Override
-        public void writeTo(TransportPort value, ChannelBuffer c) {
-            c.writeShort(value.port);
-        }
-
-        @Override
-        public TransportPort readFrom(ChannelBuffer c) throws OFParseError {
-            return TransportPort.of((c.readUnsignedShort() & 0x0FFFF));
-        }
-
+    public static TransportPort read2Bytes(ChannelBuffer c) throws OFParseError {
+        return TransportPort.of((c.readUnsignedShort() & 0x0FFFF));
     }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java b/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java
index 0a7b7c5..2f406c8 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java
@@ -49,38 +49,13 @@
     public int getLength() {
         return LENGTH;
     }
-
-    volatile byte[] bytesCache = null;
-
-    public byte[] getBytes() {
-        if (bytesCache == null) {
-            synchronized (this) {
-                if (bytesCache == null) {
-                    bytesCache =
-                            new byte[] { pcp };
-                }
-            }
-        }
-        return bytesCache;
+    
+    public void writeByte(ChannelBuffer c) {
+        c.writeShort(this.pcp);
     }
-    
-    public static final Serializer<VlanPcp> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<VlanPcp> SERIALIZER_V11 = SERIALIZER_V10;
-    public static final Serializer<VlanPcp> SERIALIZER_V12 = SERIALIZER_V10;
-    public static final Serializer<VlanPcp> SERIALIZER_V13 = SERIALIZER_V10;
-    
-    private static class SerializerV10 implements OFValueType.Serializer<VlanPcp> {
 
-        @Override
-        public void writeTo(VlanPcp value, ChannelBuffer c) {
-            c.writeShort(value.pcp);
-        }
-
-        @Override
-        public VlanPcp readFrom(ChannelBuffer c) throws OFParseError {
-            return VlanPcp.of((byte)(c.readUnsignedByte() & 0xFF));
-        }
-        
+    public static VlanPcp readByte(ChannelBuffer c) throws OFParseError {
+        return VlanPcp.of((byte)(c.readUnsignedByte() & 0xFF));
     }
     
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java
index 11c733d..a2b38b2 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java
@@ -66,23 +66,12 @@
         return bytesCache;
     }
     
-    public static final Serializer<VlanVid> SERIALIZER_V10 = new SerializerV10();
-    public static final Serializer<VlanVid> SERIALIZER_V11 = SERIALIZER_V10;
-    public static final Serializer<VlanVid> SERIALIZER_V12 = SERIALIZER_V10;
-    public static final Serializer<VlanVid> SERIALIZER_V13 = SERIALIZER_V10;
-    
-    private static class SerializerV10 implements OFValueType.Serializer<VlanVid> {
+    public void write2Bytes(ChannelBuffer c) {
+        c.writeShort(this.vid);
+    }
 
-        @Override
-        public void writeTo(VlanVid value, ChannelBuffer c) {
-            c.writeShort(value.vid);
-        }
-
-        @Override
-        public VlanVid readFrom(ChannelBuffer c) throws OFParseError {
-            return VlanVid.of(c.readShort());
-        }
-        
+    public VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
+        return VlanVid.of(c.readShort());
     }
     
 }
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
index 8a8c3e0..d344021 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
@@ -42,6 +42,27 @@
             "1.x.3.4",
             "1.2x.3.4"
     };
+    
+    String[] ipsWithMask = {
+                            "1.2.3.4/24",
+                            "192.168.130.140/255.255.192.0",
+                            "127.0.0.1/8",
+                            "8.8.8.8",
+    };
+    
+    boolean[] hasMask = {
+                         true,
+                         true,
+                         true,
+                         false
+    };
+    
+    byte[][][] ipsWithMaskValues = {
+                             new byte[][] { new byte[] { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00 } },
+                             new byte[][] { new byte[] { (byte)0xC0, (byte)0xA8, (byte)0x82, (byte)0x8C }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xC0, (byte)0x00 } },
+                             new byte[][] { new byte[] { (byte)0x7F, (byte)0x00, (byte)0x00, (byte)0x01 }, new byte[] { (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0x00 } },
+                             new byte[][] { new byte[] { (byte)0x08, (byte)0x08, (byte)0x08, (byte)0x08 }, null }
+    };
 
 
     @Test
@@ -67,7 +88,7 @@
     @Test
     public void testReadFrom() throws OFParseError, OFShortRead {
         for(int i=0; i < testAddresses.length; i++ ) {
-            IPv4 ip = IPv4.SERIALIZER_V10.readFrom(ChannelBuffers.copiedBuffer(testAddresses[i]));
+            IPv4 ip = IPv4.read4Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
             assertEquals(testInts[i], ip.getInt());
             assertArrayEquals(testAddresses[i], ip.getBytes());
             assertEquals(testStrings[i], ip.toString());
@@ -86,4 +107,31 @@
             }
         }
     }
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testOfPossiblyMasked() throws OFParseError, OFShortRead {
+        for (int i = 0; i < ipsWithMask.length; i++) {
+            OFValueType value = IPv4WithMask.ofPossiblyMasked(ipsWithMask[i]);
+            if (value instanceof IPv4 && !hasMask[i]) {
+                // Types OK, check values
+                IPv4 ip = (IPv4)value;
+                assertArrayEquals(ipsWithMaskValues[i][0], ip.getBytes());
+            } else if (value instanceof Masked && hasMask[i]) {
+                Masked<IPv4> ip = null;
+                try {
+                    ip = (Masked<IPv4>)value;
+                } catch (ClassCastException e) {
+                    fail("Invalid Masked<T> type.");
+                }
+                // Types OK, check values
+                assertArrayEquals(ipsWithMaskValues[i][0], ip.getValue().getBytes());
+                assertArrayEquals(ipsWithMaskValues[i][1], ip.getMask().getBytes());
+            } else if (value instanceof IPv4) {
+                fail("Expected masked IPv4, got unmasked IPv4.");
+            } else {
+                fail("Expected unmasked IPv4, got masked IPv4.");
+            }
+        }
+    }
 }
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
index 9782429..f2f6fe8 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
@@ -21,6 +21,72 @@
             "ffe0::",
             "1:2:3:4:5:6:7:8"
     };
+    
+    String[] ipsWithMask = {
+                            "1::1/80",
+                            "1:2:3:4::/ffff:ffff:ffff:ff00::",
+                            "ffff:ffee:1::/ff00:ff00:ff00:ff00::",
+                            "8:8:8:8:8:8:8:8",
+    };
+    
+    byte[][] masks = {
+                    new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 
+                                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 
+                                 (byte)0xff, (byte)0xff, (byte)0x00, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
+                    new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 
+                                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
+                    new byte[] { (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00, 
+                                 (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
+                    new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }
+    };
+    
+    boolean[] hasMask = {
+                         true,
+                         true,
+                         true,
+                         false
+    };
+
+    @Test
+    public void testMasked() throws UnknownHostException {
+        for(int i=0; i < ipsWithMask.length; i++ ) {
+            OFValueType value = IPv6WithMask.ofPossiblyMasked(ipsWithMask[i]);
+            if (value instanceof IPv6 && !hasMask[i]) {
+                // Types OK, check values
+                IPv6 ip = (IPv6)value;
+                InetAddress inetAddress = InetAddress.getByName(ipsWithMask[i]);
+
+                assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
+                assertEquals(ipsWithMask[i], ip.toString());
+            } else if (value instanceof IPv6WithMask && hasMask[i]) {
+                IPv6WithMask ip = null;
+                try {
+                    ip = (IPv6WithMask)value;
+                } catch (ClassCastException e) {
+                    fail("Invalid Masked<T> type.");
+                }
+                // Types OK, check values
+                InetAddress inetAddress = InetAddress.getByName(ipsWithMask[i].substring(0, ipsWithMask[i].indexOf('/')));
+
+                assertArrayEquals(ip.value.getBytes(), inetAddress.getAddress());
+                assertEquals(ipsWithMask[i].substring(0, ipsWithMask[i].indexOf('/')), ip.value.toString());
+                assertArrayEquals(masks[i], ip.mask.getBytes());
+            } else if (value instanceof IPv6) {
+                fail("Expected masked IPv6, got unmasked IPv6.");
+            } else {
+                fail("Expected unmasked IPv6, got masked IPv6.");
+            }
+        }
+    }
+
 
     @Test
     public void testOfString() throws UnknownHostException {
@@ -47,7 +113,7 @@
     public void testReadFrom() throws OFParseError, OFShortRead, UnknownHostException {
         for(int i=0; i < testStrings.length; i++ ) {
             byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
-            IPv6 ip = IPv6.SERIALIZER_V12.readFrom(ChannelBuffers.copiedBuffer(bytes));
+            IPv6 ip = IPv6.read16Bytes(ChannelBuffers.copiedBuffer(bytes));
             assertEquals(testStrings[i], ip.toString());
             assertArrayEquals(bytes, ip.getBytes());
         }
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java b/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
index f6326d1..78728e1 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
@@ -64,7 +64,7 @@
     @Test
     public void testReadFrom() throws OFParseError, OFShortRead {
         for(int i=0; i < testAddresses.length; i++ ) {
-            MacAddress ip = MacAddress.SERIALIZER_V10.readFrom(ChannelBuffers.copiedBuffer(testAddresses[i]));
+            MacAddress ip = MacAddress.read6Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
             assertEquals(testInts[i], ip.getLong());
             assertArrayEquals(testAddresses[i], ip.getBytes());
             assertEquals(testStrings[i], ip.toString());