Merge remote-tracking branch 'yotam/master'
diff --git a/Makefile b/Makefile
index dceb3e6..cb60398 100644
--- a/Makefile
+++ b/Makefile
@@ -100,17 +100,9 @@
 	PYTHONPATH=${LOXI_OUTPUT_DIR}/pyloxi:. python py_gen/tests/of12.py
 	PYTHONPATH=${LOXI_OUTPUT_DIR}/pyloxi:. python py_gen/tests/of13.py
 
-CTEST_EXEC = ${LOXI_OUTPUT_DIR}/locitest/locitest
-CTEST_SOURCE = ${LOXI_OUTPUT_DIR}/locitest/src/*.c
-CTEST_SOURCE += ${LOXI_OUTPUT_DIR}/loci/src/*.c
-CTEST_INC = -I ${LOXI_OUTPUT_DIR}/loci/inc
-CTEST_INC += -I ${LOXI_OUTPUT_DIR}/locitest/inc
-CTEST_INC += -I ${LOXI_OUTPUT_DIR}/loci/src
-CTEST_CFLAGS = -Wall -Werror -g
-
 check-c: c
-	gcc ${CTEST_CFLAGS} -o ${CTEST_EXEC} ${CTEST_SOURCE} ${CTEST_INC}
-	${CTEST_EXEC}
+	make -C ${LOXI_OUTPUT_DIR}/locitest
+	${LOXI_OUTPUT_DIR}/locitest/locitest
 
 pylint:
 	pylint -E ${LOXI_PY_FILES}
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index 96614e5..9910b7f 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -66,6 +66,8 @@
 import loxi_front_end.type_maps as type_maps
 import loxi_utils.loxi_utils as loxi_utils
 import loxi_front_end.identifiers as identifiers
+import util
+import test_data
 
 def var_name_map(m_type):
     """
@@ -341,6 +343,7 @@
 extern int run_list_limits_tests(void);
 
 extern int test_ext_objs(void);
+extern int test_datafiles(void);
 
 """)
 
@@ -1967,3 +1970,16 @@
 }
 """)
 
+def gen_datafiles_tests(out, name):
+    tests = []
+    for filename in test_data.list_files():
+        data = test_data.read(filename)
+        if not 'c' in data:
+            continue
+        name = filename[:-5].replace("/", "_")
+        tests.append(dict(name=name,
+                          filename=filename,
+                          c=data['c'],
+                          binary=data['binary']))
+
+    util.render_template(out, "test_data.c", tests=tests)
diff --git a/c_gen/templates/locitest/Makefile b/c_gen/templates/locitest/Makefile
new file mode 100644
index 0000000..ed4ba13
--- /dev/null
+++ b/c_gen/templates/locitest/Makefile
@@ -0,0 +1,12 @@
+SRCS := $(wildcard src/*.c)
+SRCS += $(wildcard ../loci/src/*.c)
+
+OBJS := $(SRCS:.c=.o)
+
+CFLAGS := -Wall -Werror -g
+CFLAGS += -Iinc -I../loci/inc -I ../loci/src
+
+all: locitest
+
+locitest: $(OBJS)
+	$(CC) $^ -o $@
diff --git a/c_gen/templates/locitest/main.c b/c_gen/templates/locitest/main.c
index 3b24035..86f7ae6 100644
--- a/c_gen/templates/locitest/main.c
+++ b/c_gen/templates/locitest/main.c
@@ -41,5 +41,7 @@
 
     RUN_TEST(ext_objs);
 
+    TEST_ASSERT(test_datafiles() == TEST_PASS);
+
     return global_error;
 }
diff --git a/c_gen/templates/locitest/test_data.c b/c_gen/templates/locitest/test_data.c
new file mode 100644
index 0000000..f4e985f
--- /dev/null
+++ b/c_gen/templates/locitest/test_data.c
@@ -0,0 +1,88 @@
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University */
+/* Copyright (c) 2011, 2012 Open Networking Foundation */
+/* Copyright (c) 2012, 2013 Big Switch Networks, Inc. */
+/* See the file LICENSE.loci which should have been included in the source distribution */
+
+/**
+ *
+ * AUTOMATICALLY GENERATED FILE.  Edits will be lost on regen.
+ *
+ * Data file tests for all versions.
+ */
+
+#include <locitest/test_common.h>
+
+<?py
+def hexarray(data, indent):
+    i = 0
+    text = []
+    text.append(" " * indent)
+    for byte in data:
+        text.append("0x%02x, " % ord(byte))
+        i += 1
+        if i == 8:
+            text.append("\n" + " " * indent)
+            i = 0
+        #endif
+    #endfor
+    return "".join(text)
+#end
+?>
+
+static void
+hexdump(const uint8_t *data, int len)
+{
+    int i = 0, j;
+    while (i < len) {
+	printf("%02x: ", i);
+	for (j = 0; j < 8 && i < len; j++, i++) {
+	    printf("%02x ", data[i]);
+	}
+	printf("\n");
+    }
+}
+
+static void
+show_failure(const uint8_t *a, int a_len, const uint8_t *b, int b_len)
+{
+    printf("\n--- Expected: (len=%d)\n", a_len);
+    hexdump(a, a_len);
+    printf("\n--- Actual: (len=%d)\n", b_len);
+    hexdump(b, b_len);
+}
+
+:: for test in tests:
+/* Generated from ${test['filename']} */
+static int
+test_${test['name']}(void) {
+    uint8_t binary[] = {
+${hexarray(test['binary'], indent=8)}
+    };
+
+    of_object_t *obj;
+
+${'\n'.join([' ' * 4 + x for x in test['c'].split("\n")])}
+
+    if (sizeof(binary) != WBUF_CURRENT_BYTES(OF_OBJECT_TO_WBUF(obj))
+        || memcmp(binary, WBUF_BUF(OF_OBJECT_TO_WBUF(obj)), sizeof(binary))) {
+	show_failure(binary, sizeof(binary),
+		     WBUF_BUF(OF_OBJECT_TO_WBUF(obj)),
+		     WBUF_CURRENT_BYTES(OF_OBJECT_TO_WBUF(obj)));
+	of_object_delete(obj);
+	return TEST_FAIL;
+    }
+
+    of_object_delete(obj);
+    return TEST_PASS;
+}
+
+:: #endfor
+
+int
+test_datafiles(void)
+{
+:: for test in tests:
+    RUN_TEST(${test['name']});
+:: #endfor
+    return TEST_PASS;
+}
diff --git a/generic_utils.py b/generic_utils.py
index eeb26d6..0bf289e 100644
--- a/generic_utils.py
+++ b/generic_utils.py
@@ -31,6 +31,7 @@
 Intended to be imported into another namespace
 """
 
+import collections
 import functools
 import sys
 import of_g
@@ -99,8 +100,6 @@
 #
 ################################################################
 
-import collections
-
 class OrderedSet(collections.MutableSet):
     """
     A set implementations that retains insertion order.  From the receipe
@@ -164,6 +163,59 @@
             return len(self) == len(other) and list(self) == list(other)
         return set(self) == set(other)
 
+################################################################
+#
+# OrderedDefaultDict
+#
+################################################################
+
+class OrderedDefaultDict(collections.OrderedDict):
+    """
+    A Dictionary that maintains insertion order where missing values
+    are provided by a factory function, i.e., a combination of
+    the semantics of collections.defaultdict and collections.OrderedDict.
+    """
+    def __init__(self, default_factory=None, *a, **kw):
+        if (default_factory is not None and
+                not callable(default_factory)):
+            raise TypeError('first argument must be callable')
+        collections.OrderedDict.__init__(self, *a, **kw)
+        self.default_factory = default_factory
+
+    def __getitem__(self, key):
+        try:
+            return collections.OrderedDict.__getitem__(self, key)
+        except KeyError:
+            return self.__missing__(key)
+
+    def __missing__(self, key):
+        if self.default_factory is None:
+            raise KeyError(key)
+        self[key] = value = self.default_factory()
+        return value
+
+    def __reduce__(self):
+        if self.default_factory is None:
+            args = tuple()
+        else:
+            args = self.default_factory,
+        return type(self), args, None, None, self.items()
+
+    def copy(self):
+        return self.__copy__()
+
+    def __copy__(self):
+        return type(self)(self.default_factory, self)
+
+    def __deepcopy__(self, memo):
+        import copy
+        return type(self)(self.default_factory,
+                          copy.deepcopy(self.items()))
+    def __repr__(self):
+        return 'OrderedDefaultDict(%s, %s)' % (self.default_factory,
+                                        collections.OrderedDict.__repr__(self))
+
+
 def find(iterable, func):
     """
     find the first item in iterable for which func returns something true'ish.
diff --git a/java_gen/codegen.py b/java_gen/codegen.py
index 0765c91..258b81c 100644
--- a/java_gen/codegen.py
+++ b/java_gen/codegen.py
@@ -36,6 +36,7 @@
 import of_g
 from loxi_ir import *
 import lang_java
+import test_data
 
 import loxi_utils.loxi_utils as loxi_utils
 
@@ -43,17 +44,17 @@
 
 def gen_all_java(out, name):
     basedir= '%s/openflowj' % of_g.options.install_dir
-    srcdir = "%s/src/main/java/" % basedir
     print "Outputting to %s" % basedir
     if os.path.exists(basedir):
         shutil.rmtree(basedir)
     os.makedirs(basedir)
     copy_prewrite_tree(basedir)
 
-    gen = JavaGenerator(srcdir)
+    gen = JavaGenerator(basedir)
     gen.create_of_interfaces()
     gen.create_of_classes()
     gen.create_of_const_enums()
+    gen.create_of_factories()
 
     with open('%s/README.java-lang' % os.path.dirname(__file__)) as readme_src:
         out.writelines(readme_src.readlines())
@@ -67,11 +68,14 @@
         self.basedir = basedir
         self.java_model = java_model.model
 
-    def render_class(self, clazz, template, **context):
+    def render_class(self, clazz, template, src_dir=None, **context):
+        if not src_dir:
+            src_dir = "src/main/java/"
+
         context['class_name'] = clazz.name
         context['package'] = clazz.package
 
-        filename = os.path.join(self.basedir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
+        filename = os.path.join(self.basedir, src_dir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
         dirname = os.path.dirname(filename)
         if not os.path.exists(dirname):
             os.makedirs(dirname)
@@ -87,6 +91,10 @@
             self.render_class(clazz=enum,
                     template='const.java', enum=enum, all_versions=self.java_model.versions)
 
+            for version in enum.versions:
+                clazz = java_model.OFGenericClass(package="org.openflow.protocol.ver{}".format(version.of_version), name="{}SerializerVer{}".format(enum.name, version.of_version))
+                self.render_class(clazz=clazz, template="const_serializer.java", enum=enum, version=version)
+
     def create_of_interfaces(self):
         """ Create the base interfaces for of classes"""
         for interface in self.java_model.interfaces:
@@ -98,15 +106,30 @@
     def create_of_classes(self):
         """ Create the OF classes with implementations for each of the interfaces and versions """
         for interface in self.java_model.interfaces:
-            if interface.name == "OFTableMod":
-                continue
-            if not loxi_utils.class_is_message(interface.c_name) and not loxi_utils.class_is_oxm(interface.c_name):
-                continue
             for java_class in interface.versioned_classes:
+                if not self.java_model.generate_class(java_class):
+                    continue
                 self.render_class(clazz=java_class,
                         template='of_class.java', version=java_class.version, msg=java_class,
                         impl_class=java_class.name)
 
+                self.create_unit_test(java_class.unit_test)
+
+    def create_unit_test(self, unit_test):
+        if unit_test.has_test_data:
+            self.render_class(clazz=unit_test,
+                    template='unit_test.java', src_dir="src/test/java",
+                    version=unit_test.java_class.version,
+                    test=unit_test, msg=unit_test.java_class,
+                    test_data=unit_test.test_data)
+
+    def create_of_factories(self):
+        factory = self.java_model.of_factory
+        self.render_class(clazz=factory, template="of_factory_interface.java", factory=factory)
+        for factory_class in factory.factory_classes:
+            self.render_class(clazz=factory_class, template="of_factory_class.java", factory=factory_class, model=self.java_model)
+        self.render_class(clazz=java_model.OFGenericClass(package="org.openflow.protocol", name="OFFactories"), template="of_factories.java", versions=self.java_model.versions)
+
 def copy_prewrite_tree(basedir):
     """ Recursively copy the directory structure from ./java_gen/pre-write
        into $basedir"""
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 35f334c..6f5cfaa 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -29,24 +29,26 @@
 # A lot of this stuff could/should probably be merged with the python utilities
 
 import collections
-from collections import namedtuple, defaultdict
+from collections import namedtuple, defaultdict, OrderedDict
 import logging
 import os
 import pdb
 import re
 
-from generic_utils import find, memoize, OrderedSet
+from generic_utils import find, memoize, OrderedSet, OrderedDefaultDict
 import of_g
 from loxi_ir import *
 import loxi_front_end.type_maps as type_maps
-import loxi_utils.loxi_utils as utils
+import loxi_utils.loxi_utils as loxi_utils
 import py_gen.util as py_utils
+import test_data
 
 import java_gen.java_type as java_type
 
 class JavaModel(object):
-    write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)))
-    virtual_interfaces = set(['OFOxm' ])
+    enum_blacklist = set(("OFDefinitions","OFFlowWildcards"))
+    write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)), OFAction=set(('type',)))
+    virtual_interfaces = set(['OFOxm', 'OFAction' ])
 
     @property
     @memoize
@@ -56,12 +58,15 @@
     @property
     @memoize
     def interfaces(self):
-        version_map_per_class = collections.defaultdict(lambda: {})
+        version_map_per_class = collections.OrderedDict()
 
         for raw_version, of_protocol in of_g.ir.items():
             jversion = JavaOFVersion(of_protocol.wire_version)
 
             for of_class in of_protocol.classes:
+                if not of_class.name in version_map_per_class:
+                    version_map_per_class[of_class.name] = collections.OrderedDict()
+
                 version_map_per_class[of_class.name][jversion] = of_class
 
         interfaces = []
@@ -73,17 +78,18 @@
     @property
     @memoize
     def enums(self):
-        enum_entry_version_value_map = collections.defaultdict(lambda: collections.defaultdict(lambda: collections.OrderedDict()))
+        name_version_enum_map = OrderedDefaultDict(lambda: OrderedDict())
 
         for version in self.versions:
             of_protocol = of_g.ir[version.int_version]
             for enum in of_protocol.enums:
-                for entry_name, entry_value in enum.values:
-                    enum_entry_version_value_map[enum.name][entry_name][version] = entry_value
+                name_version_enum_map[enum.name][version] = enum
 
-        enums = [ JavaEnum(name, entry_version_value_map) for name, entry_version_value_map
-                        in enum_entry_version_value_map.items() ]
+        enums = [ JavaEnum(name, version_enum_map) for name, version_enum_map,
+                        in name_version_enum_map.items() ]
 
+        # inelegant - need java name here
+        enums = [ enum for enum in enums if enum.name not in self.enum_blacklist ]
         return enums
 
     @memoize
@@ -93,6 +99,41 @@
         except KeyError:
             raise KeyError("Could not find enum with name %s" % name)
 
+    @property
+    @memoize
+    def of_factory(self):
+           return OFFactory(
+                    package="org.openflow.protocol",
+                    name="OFFactory",
+                    members=self.interfaces)
+
+    def generate_class(self, clazz):
+        if clazz.interface.is_virtual:
+            return False
+        if clazz.interface.name == "OFTableMod":
+            return False
+        if loxi_utils.class_is_message(clazz.interface.c_name):
+            return True
+        if loxi_utils.class_is_oxm(clazz.interface.c_name):
+            return True
+        else:
+            return False
+
+
+class OFFactory(namedtuple("OFFactory", ("package", "name", "members"))):
+    @property
+    def factory_classes(self):
+            return [ OFFactoryClass(
+                    package="org.openflow.protocol.ver{}".format(version.of_version),
+                    name="OFFactoryVer{}".format(version.of_version),
+                    interface=self,
+                    version=version
+                    ) for version in model.versions ]
+
+
+OFGenericClass = namedtuple("OFGenericClass", ("package", "name"))
+OFFactoryClass = namedtuple("OFFactory", ("package", "name", "interface", "version"))
+
 model = JavaModel()
 
 #######################################################################
@@ -139,7 +180,7 @@
         self.c_name = c_name
         self.version_map = version_map
         self.name = java_type.name_c_to_caps_camel(c_name)
-        self.builder_name = self.name + "Builder"
+        self.variable_name = self.name[2].lower() + self.name[3:]
         self.constant_name = c_name.upper().replace("OF_", "")
 
         pck_suffix, parent_interface = self.class_info()
@@ -152,15 +193,15 @@
     def class_info(self):
         if re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
             return ("", "OFFlowMod")
-        elif utils.class_is_message(self.c_name):
+        elif loxi_utils.class_is_message(self.c_name):
             return ("", "OFMessage")
-        elif utils.class_is_action(self.c_name):
+        elif loxi_utils.class_is_action(self.c_name):
             return ("action", "OFAction")
-        elif utils.class_is_oxm(self.c_name):
+        elif loxi_utils.class_is_oxm(self.c_name):
             return ("oxm", "OFOxm")
-        elif utils.class_is_instruction(self.c_name):
+        elif loxi_utils.class_is_instruction(self.c_name):
             return ("instruction", "OFInstruction")
-        elif utils.class_is_meter_band(self.c_name):
+        elif loxi_utils.class_is_meter_band(self.c_name):
             return ("meterband", "OFMeterBand")
         else:
             return ("", None)
@@ -188,10 +229,17 @@
         return self.name in model.virtual_interfaces
 
     @property
+    def is_universal(self):
+        return len(self.all_versions) == len(model.versions)
+
+    @property
     @memoize
     def all_versions(self):
         return self.version_map.keys()
 
+    def has_version(self, version):
+        return version in self.version_map
+
     def versioned_class(self, version):
         return JavaOFClass(self, version, self.version_map[version])
 
@@ -218,12 +266,22 @@
         self.version = version
         self.constant_name = self.c_name.upper().replace("OF_", "")
         self.package = "org.openflow.protocol.ver%s" % version.of_version
+        self.generated = False
+
+    @property
+    @memoize
+    def unit_test(self):
+        return JavaUnitTest(self)
 
     @property
     def name(self):
         return "%sVer%s" % (self.interface.name, self.version.of_version)
 
     @property
+    def variable_name(self):
+        return self.name[3:]
+
+    @property
     def length(self):
         if self.is_fixed_length:
             return self.min_length
@@ -403,7 +461,7 @@
         if hasattr(self.member, "length"):
             return self.member.length
         else:
-            count, base = utils.type_dec_to_count_base(self.member.type)
+            count, base = loxi_utils.type_dec_to_count_base(self.member.type)
             return of_g.of_base_types[base]['bytes'] * count
 
     @staticmethod
@@ -441,22 +499,70 @@
             return False
         return (self.name,) == (other.name,)
 
+
+#######################################################################
+### Unit Test
+#######################################################################
+
+class JavaUnitTest(object):
+    def __init__(self, java_class):
+        self.java_class = java_class
+        self.data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
+                                                     name=java_class.c_name[3:])
+    @property
+    def package(self):
+        return self.java_class.package
+
+    @property
+    def name(self):
+        return self.java_class.name + "Test"
+
+    @property
+    def has_test_data(self):
+        return test_data.exists(self.data_file_name)
+
+    @property
+    @memoize
+    def test_data(self):
+        return test_data.read(self.data_file_name)
+
+
 #######################################################################
 ### Enums
 #######################################################################
 
 class JavaEnum(object):
-    def __init__(self, c_name, entry_version_value_map):
+    def __init__(self, c_name, version_enum_map):
         self.c_name = c_name
         self.name   = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
 
         # Port_features has constants that start with digits
         self.name_prefix = "PF_" if self.name == "OFPortFeatures" else ""
 
+        self.version_enums = version_enum_map
+
+        entry_name_version_value_map = OrderedDefaultDict(lambda: OrderedDict())
+        for version, ir_enum in version_enum_map.items():
+            for ir_entry in ir_enum.entries:
+                if "virtual" in ir_entry.params:
+                    continue
+                entry_name_version_value_map[ir_entry.name][version] = ir_entry.value
+
         self.entries = [ JavaEnumEntry(self, name, version_value_map)
-                         for (name, version_value_map) in entry_version_value_map.items() ]
+                         for (name, version_value_map) in entry_name_version_value_map.items() ]
         self.package = "org.openflow.protocol"
 
+    def wire_type(self, version):
+        ir_enum = self.version_enums[version]
+        if "wire_type" in ir_enum.params:
+            return java_type.convert_enum_wire_type_to_jtype(ir_enum.params["wire_type"])
+        else:
+            return java_type.u8
+
+    @property
+    def versions(self):
+        return self.version_enums.keys()
+
     @memoize
     def entry_by_name(self, name):
         try:
@@ -481,11 +587,18 @@
 # values: Map JavaVersion->Value
 class JavaEnumEntry(object):
     def __init__(self, enum, name, values):
+        self.enum = enum
         self.name = enum.name_prefix + "_".join(name.split("_")[1:]).upper()
         self.values = values
 
+    def has_value(self, version):
+        return version in self.values
+
     def value(self, version):
-        res = self.version_value_map[version]
+        return self.values[version]
+
+    def format_value(self, version):
+        res = self.enum.wire_type(version).format_value(self.values[version])
         return res
 
     def all_values(self, versions, not_present=None):
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 8580f37..2d8a547 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -21,19 +21,19 @@
         return camel
 
 
-ANY = 0xFFFFFFFFFFFFFFFF
+java_primitive_types = set("byte char short int long".split(" "))
 
+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):
@@ -54,6 +54,21 @@
         self.ops[version] = VersionOp(version, read, write)
         return self
 
+    def cast(self, min):
+        """ declares that the value has to be cast to itself for values >= min.
+            This is to deal with Java signedness """
+        def format_cast_value(value):
+            if value >= min:
+                return "(%s) 0x%x" % (self.pub_type, value)
+            else:
+                return "0x%x" % (value)
+
+        self.format_value = format_cast_value
+        return self
+
+    def format_value(self, value):
+        return value
+
     @property
     def public_type(self):
         """ return the public type """
@@ -98,6 +113,15 @@
         else:
             return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
 
+    @property
+    def is_primitive(self):
+        return self.pub_type in java_primitive_types
+
+    @property
+    def is_array(self):
+        return self.pub_type.endswith("[]")
+
+
 hello_elem_list = JType("List<OFHelloElement>") \
         .op(read='ChannelUtils.readHelloElementList(bb)', write='ChannelUtils.writeHelloElementList(bb)')
 u8 =  JType('byte',  size=1) \
@@ -176,6 +200,8 @@
 ipv6 = JType("IPv6") \
         .op(read="IPv6.read16Bytes(bb)", \
             write="$name.write16Bytes(bb)")
+packetin_reason = JType("OFPacketInReason")\
+        .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)", write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)")
 
 default_mtype_to_jtype_convert_map = {
         'uint8_t' : u8,
@@ -213,12 +239,23 @@
 
 ## This is where we drop in special case handling for certain types
 exceptions = {
-        'OFPacketIn': {
-            'data' : octets
+        'of_packet_in': {
+            'data' : octets,
+            'reason': packetin_reason
             },
 }
 
 
+enum_wire_types = {
+        "uint8_t": JType("byte").op(read="bb.readByte()", write="bb.writeByte($name)").cast(min=1<<7),
+        "uint16_t": JType("short").op(read="bb.readShort()", write="bb.writeShort($name)").cast(min=1<<15),
+        "uint32_t": JType("int").op(read="bb.readInt()", write="bb.writeInt($name)").cast(min=1<<31),
+        "uint64_t": JType("long").op(read="bb.readLong()", write="bb.writeLong($name)").cast(min=1<<31)
+}
+
+def convert_enum_wire_type_to_jtype(wire_type):
+    return enum_wire_types[wire_type]
+
 def make_standard_list_jtype(c_type):
     m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
     if not m:
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFMeterBand.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFMeterBand.java
deleted file mode 100644
index d15812b..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFMeterBand.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.openflow.types;
-
-public interface OFMeterBand {
-
-}
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 9dc197f..f6dc408 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
@@ -520,7 +520,7 @@
     }
 
     public static OFPort read2Bytes(ChannelBuffer c) throws OFParseError {
-        return OFPort.of((c.readUnsignedShort() & 0x0FFFF));
+        return OFPort.ofShort(c.readShort());
     }
 
     public void write4Bytes(ChannelBuffer c) {
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
index dab6ff2..afd03ad 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
@@ -22,9 +22,9 @@
 import org.openflow.protocol.action.OFAction;
 import org.openflow.protocol.instruction.OFInstruction;
 import org.openflow.protocol.match.Match;
+import org.openflow.protocol.meterband.OFMeterBand;
 import org.openflow.types.OFFlowModCmd;
 import org.openflow.types.OFHelloElement;
-import org.openflow.types.OFMeterBand;
 import org.openflow.types.OFPhysicalPort;
 
 import com.google.common.base.Charsets;
@@ -43,18 +43,19 @@
         return byteArray;
     }
 
-    static public void writeBytes(final ChannelBuffer bb, final byte byteArray[]) {
+    static public void writeBytes(final ChannelBuffer bb,
+            final byte byteArray[]) {
         bb.writeBytes(byteArray);
     }
 
-    public static List<OFPhysicalPort> readPhysicalPortList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPhysicalPort> readPhysicalPortList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFInstruction> readInstructionsList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFInstruction> readInstructionsList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -69,12 +70,14 @@
         return null;
     }
 
-    public static List<OFAction> readActionsList(final ChannelBuffer bb, final int i) {
+    public static List<OFAction> readActionsList(final ChannelBuffer bb,
+            final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBsnInterface> readBsnInterfaceList(final ChannelBuffer bb) {
+    public static List<OFBsnInterface> readBsnInterfaceList(
+            final ChannelBuffer bb) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -84,22 +87,24 @@
         return null;
     }
 
-    public static List<OFPacketQueue> readPacketQueueList(final ChannelBuffer bb,
+    public static List<OFPacketQueue> readPacketQueueList(
+            final ChannelBuffer bb, final int i) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static List<OFHelloElement> readHelloElementList(
+            final ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static List<OFBucket> readBucketList(final ChannelBuffer bb,
             final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFHelloElement> readHelloElementList(final ChannelBuffer bb) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public static List<OFBucket> readBucketList(final ChannelBuffer bb, final int i) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
     public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb) {
         // TODO Auto-generated method stub
         return null;
@@ -126,18 +131,21 @@
         return new String(dst, Charsets.US_ASCII);
     }
 
-    public static void writeFixedLengthString(ChannelBuffer bb, String string, int length) {
+    public static void writeFixedLengthString(ChannelBuffer bb, String string,
+            int length) {
         int l = string.length();
-        if(l > length) {
-            throw new IllegalArgumentException("Error writing string: length="+l+" > max Length="+length);
+        if (l > length) {
+            throw new IllegalArgumentException("Error writing string: length="
+                    + l + " > max Length=" + length);
         }
         bb.writeBytes(string.getBytes(Charsets.US_ASCII));
-        if(l < length) {
+        if (l < length) {
             bb.writeZero(length - l);
         }
     }
 
-    public static void writeBsnInterfaceList(ChannelBuffer bb, List<OFBsnInterface> interfaces) {
+    public static void writeBsnInterfaceList(ChannelBuffer bb,
+            List<OFBsnInterface> interfaces) {
         // TODO Auto-generated method stub
 
     }
@@ -312,5 +320,4 @@
 
     }
 
-
 }
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
index 7700546..50ba198 100644
--- a/java_gen/templates/_imports.java
+++ b/java_gen/templates/_imports.java
@@ -1,7 +1,9 @@
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.openflow.protocol.*;
 import org.openflow.protocol.action.*;
+import org.openflow.protocol.meterband.*;
 import org.openflow.protocol.instruction.*;
 import org.openflow.protocol.match.*;
 import org.openflow.protocol.oxm.*;
@@ -10,3 +12,4 @@
 import org.openflow.util.*;
 import org.openflow.exceptions.*;
 import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
diff --git a/java_gen/templates/_singleton.java b/java_gen/templates/_singleton.java
new file mode 100644
index 0000000..8ea9f01
--- /dev/null
+++ b/java_gen/templates/_singleton.java
@@ -0,0 +1,10 @@
+
+    private ${msg.name}() {}
+
+    private final static class Holder {
+        private static final ${msg.name} INSTANCE = new ${msg.name}();
+    }
+
+    public static ${msg.name} getInstance() {
+        return Holder.INSTANCE;
+    }
diff --git a/java_gen/templates/const.java b/java_gen/templates/const.java
index 7870529..11c09ab 100644
--- a/java_gen/templates/const.java
+++ b/java_gen/templates/const.java
@@ -37,16 +37,7 @@
 
 public enum ${class_name} {
 //:: for i, entry in enumerate(enum.entries):
-//::     values = [ ("0x%x" % val) if val is not None else "-1" for val in entry.all_values(all_versions) ]
-     ${entry.name}(new int[] { ${ ", ".join( values) } } )${ ", " if i < len(enum.entries)-1 else ";" }
+     ${entry.name}${ ", " if i < len(enum.entries)-1 else ";" }
 //:: #endfor
 
-    private final int[] wireValues;
-    ${class_name}(int[] wireValues) {
-        this.wireValues = wireValues;
-    }
-
-    public int getWireValue(OFVersion version) {
-        return this.wireValues[version.getWireVersion()];
-    }
 }
diff --git a/java_gen/templates/const_serializer.java b/java_gen/templates/const_serializer.java
new file mode 100644
index 0000000..4e21070
--- /dev/null
+++ b/java_gen/templates/const_serializer.java
@@ -0,0 +1,85 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package ${package};
+
+import org.openflow.types.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.protocol.OFVersion;
+import ${enum.package}.${enum.name};
+
+public class ${class_name} {
+    //:: wire_type = enum.wire_type(version)
+    //:: int_wire_type = enum.wire_type(version).pub_type
+    //:: entries = sorted([ (entry, entry.value(version)) for entry in enum.entries if entry.has_value(version) ], lambda (_,va), (_2,vb): va.__cmp__(vb))
+
+    //:: for entry, _ in entries:
+    public final static ${int_wire_type} ${entry.name}_VAL = ${entry.format_value(version)};
+    //:: #endfor
+
+    public static ${enum.name} readFrom(ChannelBuffer bb) throws OFParseError {
+        try {
+            return ofWireValue(${wire_type.read_op(version)});
+        } catch (IllegalArgumentException e) {
+            throw new OFParseError(e);
+        }
+    }
+
+    public static void writeTo(ChannelBuffer bb, ${enum.name} e) {
+        ${wire_type.write_op(version=version, name="toWireValue(e)")};
+    }
+
+    public static ${enum.name} ofWireValue(${int_wire_type} val) {
+        switch(val) {
+        //:: for entry, _ in entries:
+            case ${entry.name}_VAL:
+                return ${enum.name}.${entry.name};
+        //:: #endfor
+            default:
+                throw new IllegalArgumentException("Illegal wire value for type ${enum.name} in version ${version}: " + val);
+        }
+    }
+
+    public static ${int_wire_type} toWireValue(${enum.name} e) {
+        switch(e) {
+        //:: for entry, _ in entries:
+            case ${entry.name}:
+                return ${entry.name}_VAL;
+        //:: #endfor
+            default:
+                throw new IllegalArgumentException("Illegal enum value for type ${enum.name} in version ${version}: " + e);
+        }
+    }
+
+}
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index 9665c49..18dae2b 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -65,11 +65,11 @@
 //:: include("_field_accessors.java", msg=msg, generate_setters=False, builder=False)
 
 
-    public ${msg.name}.Builder createBuilder() {
-        return new BuilderImplWithParent(this);
+    public ${msg.interface.name}.Builder createBuilder() {
+        return new BuilderWithParent(this);
     }
 
-    static class BuilderImplWithParent implements ${msg.interface.name}.Builder {
+    static class BuilderWithParent implements ${msg.interface.name}.Builder {
         final ${impl_class} parentMessage;
 
         // OF message fields
@@ -78,7 +78,7 @@
         private ${prop.java_type.public_type} ${prop.name};
 //:: #endfor
 
-        BuilderImplWithParent(${impl_class} parentMessage) {
+        BuilderWithParent(${impl_class} parentMessage) {
             this.parentMessage = parentMessage;
         }
 
@@ -94,7 +94,7 @@
         }
     }
 
-    static class BuilderImpl implements ${msg.interface.name}.Builder {
+    static class Builder implements ${msg.interface.name}.Builder {
         // OF message fields
 //:: for prop in msg.data_members:
         private boolean ${prop.name}Set;
@@ -205,5 +205,64 @@
         }
     }
 
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder("${msg.name}(");
+        //:: for i, prop in enumerate(msg.data_members):
+        //:: if i > 0:
+        b.append(", ");
+        //:: #endif
+        b.append("${prop.name}=").append(${ "Arrays.toString(%s)" % prop.name if prop.java_type.is_array else prop.name });
+        //:: #endfor
+        b.append(")");
+        return b.toString();
+    }
+
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ${msg.name} other = (${msg.name}) obj;
+
+        //:: for prop in msg.data_members:
+        //:: if prop.java_type.is_primitive:
+        if( ${prop.name} != other.${prop.name})
+            return false;
+        //:: elif prop.java_type.is_array:
+        if (!Arrays.equals(${prop.name}, other.${prop.name}))
+                return false;
+        //:: else:
+        if (${prop.name} == null) {
+            if (other.${prop.name} != null)
+                return false;
+        } else if (!${prop.name}.equals(other.${prop.name}))
+            return false;
+        //:: #endif
+        //:: #endfor
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+
+        //:: for prop in msg.data_members:
+        //:: if prop.java_type.is_primitive:
+        result = prime * result + ${prop.name};
+        //:: elif prop.java_type.is_array:
+        result = prime * result + Arrays.hashCode(${prop.name});
+        //:: else:
+        result = prime * result + ((${prop.name} == null) ? 0 : ${prop.name}.hashCode());
+        //:: #endif
+        //:: #endfor
+        return result;
+    }
+
 
 }
diff --git a/java_gen/templates/of_factories.java b/java_gen/templates/of_factories.java
new file mode 100644
index 0000000..cce134d
--- /dev/null
+++ b/java_gen/templates/of_factories.java
@@ -0,0 +1,49 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package org.openflow.protocol;
+
+//:: include("_imports.java")
+
+public final class OFFactories {
+    public static OFFactory getFactory(OFVersion version) {
+        switch(version) {
+            //:: for v in versions:
+            case ${v.constant_version}:
+                return org.openflow.protocol.ver${v.of_version}.OFFactoryVer${v.of_version}.getInstance();
+            //:: #endfor
+            default:
+                throw new IllegalArgumentException("Unknown version: "+version);
+            }
+    }
+}
diff --git a/java_gen/templates/of_factory_class.java b/java_gen/templates/of_factory_class.java
new file mode 100644
index 0000000..8620787
--- /dev/null
+++ b/java_gen/templates/of_factory_class.java
@@ -0,0 +1,56 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package ${factory.package};
+
+//:: include("_imports.java")
+
+public class ${factory.name} implements ${factory.interface.name} {
+//:: for i in factory.interface.members:
+    //:: if i.is_virtual:
+    //::    continue
+    //:: #endif
+
+//::   if i.has_version(factory.version) and model.generate_class(i.versioned_class(factory.version)):
+    public ${i.name}.Builder create${i.name[2:]}Builder() {
+        return new ${i.versioned_class(factory.version).name}.Builder();
+    }
+//:: else:
+    public ${i.name}.Builder create${i.name[2:]}Builder() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException("${i.name} not supported in version ${factory.version}");
+    }
+//:: #endif
+//:: #endfor
+
+    //:: include("_singleton.java", msg=factory)
+}
diff --git a/java_gen/templates/of_factory_interface.java b/java_gen/templates/of_factory_interface.java
new file mode 100644
index 0000000..467504e
--- /dev/null
+++ b/java_gen/templates/of_factory_interface.java
@@ -0,0 +1,45 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package org.openflow.protocol;
+
+//:: include("_imports.java")
+
+public interface ${factory.name} {
+//:: for i in factory.members:
+    //:: if i.is_virtual:
+    //::    continue
+    //:: #endif
+    ${i.name}.Builder create${i.name[2:]}Builder()${ "" if i.is_universal else " throws UnsupportedOperationException"};
+//:: #endfor
+}
diff --git a/java_gen/templates/unit_test.java b/java_gen/templates/unit_test.java
new file mode 100644
index 0000000..1462465
--- /dev/null
+++ b/java_gen/templates/unit_test.java
@@ -0,0 +1,102 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: from loxi_ir import *
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package ${test.package};
+
+//:: include("_imports.java", msg=msg)
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class ${test.name} {
+    //:: var_type = msg.interface.name
+    //:: var_name = msg.interface.variable_name
+    OFFactory factory;
+
+    final static byte[] ${msg.constant_name}_SERIALIZED =
+        new byte[] { ${", ".join("%s0x%x" % (("" if ord(c)<128 else "(byte) "),  ord(c)) for c in test_data["binary"] ) } };
+
+    @Before
+    public void setup() {
+        factory = OFFactories.getFactory(OFVersion.${version.constant_version});
+    }
+
+    //:: if "java" in test_data:
+    @Test
+    public void testWrite() {
+        ${var_type}.Builder builder = factory.create${var_type[2:]}Builder();
+        ${test_data["java"]};
+        ${var_type} ${var_name} = builder.getMessage();
+        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+        ${var_name}.writeTo(bb);
+        byte[] written = new byte[bb.readableBytes()];
+        bb.readBytes(written);
+
+        assertArrayEquals(${msg.constant_name}_SERIALIZED, written);
+    }
+
+    @Test
+    public void testRead() throws Exception {
+        ${var_type}.Builder builder = factory.create${var_type[2:]}Builder();
+        ${test_data["java"]};
+        ${var_type} ${var_name}Built = builder.getMessage();
+
+        ChannelBuffer input = ChannelBuffers.copiedBuffer(${msg.constant_name}_SERIALIZED);
+
+        // FIXME should invoke the overall reader once implemented
+        ${var_type} ${var_name}Read = ${msg.name}.READER.readFrom(input);
+
+        assertEquals(${var_name}Read, ${var_name}Built);
+   }
+   //:: else:
+   // FIXME: No java stanza in test_data for this class. Add for more comprehensive unit testing
+   //:: #endif
+
+   @Test
+   public void testReadWrite() throws Exception {
+       ChannelBuffer input = ChannelBuffers.copiedBuffer(${msg.constant_name}_SERIALIZED);
+
+       // FIXME should invoke the overall reader once implemented
+       ${var_type} ${var_name} = ${msg.name}.READER.readFrom(input);
+
+       // write message again
+       ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+       ${var_name}.writeTo(bb);
+       byte[] written = new byte[bb.readableBytes()];
+       bb.readBytes(written);
+
+       assertArrayEquals(${msg.constant_name}_SERIALIZED, written);
+   }
+
+}
diff --git a/lang_c.py b/lang_c.py
index aae08ea..fc016f2 100644
--- a/lang_c.py
+++ b/lang_c.py
@@ -97,6 +97,7 @@
     'locitest/src/test_msg.c': c_test_gen.gen_msg_test,
     'locitest/src/test_scalar_acc.c': c_test_gen.gen_message_scalar_test,
     'locitest/src/test_uni_acc.c': c_test_gen.gen_unified_accessor_tests,
+    'locitest/src/test_data.c': c_test_gen.gen_datafiles_tests,
 
     # Static locitest code
     'locitest/inc/locitest/unittest.h': static,
@@ -107,4 +108,5 @@
     'locitest/src/test_utils.c': static,
     'locitest/src/test_validator.c': static,
     'locitest/src/main.c': static,
+    'locitest/Makefile': static,
 }
diff --git a/loxi_front_end/frontend.py b/loxi_front_end/frontend.py
index ab98c26..c12eaae 100644
--- a/loxi_front_end/frontend.py
+++ b/loxi_front_end/frontend.py
@@ -64,7 +64,14 @@
             ofclass = OFClass(name=decl_ast[1], members=members)
             ofinput.classes.append(ofclass)
         if decl_ast[0] == 'enum':
-            enum = OFEnum(name=decl_ast[1], values=[(x[0], x[1]) for x in decl_ast[2]])
+            # 0: "enum"
+            # 1: name
+            # 2: potentially list of [param_name, param_value]
+            # 3: list of [constant_name, constant_value]+
+            enum = OFEnum(name=decl_ast[1],
+                    entries=[OFEnumEntry(name=x[0], value=x[2], params={param:value for param, value in x[1] }) for x in decl_ast[3]],
+                    params = { param: value for param, value in decl_ast[2] }
+                    )
             ofinput.enums.append(enum)
         elif decl_ast[0] == 'metadata':
             if decl_ast[1] == 'version':
diff --git a/loxi_front_end/parser.py b/loxi_front_end/parser.py
index 503a05a..03d5af1 100644
--- a/loxi_front_end/parser.py
+++ b/loxi_front_end/parser.py
@@ -59,10 +59,20 @@
          s('}') - s(';')
 
 # Enums
-enum_member = P.Group(identifier + s('=') + integer)
+enum_param_name = kw("wire_type") | kw("bitmask") | kw("complete")
+enum_param = P.Group(enum_param_name  - s('=') - any_type)
+enum_param_list = P.Forward()
+enum_param_list << enum_param + P.Optional(s(',') + P.Optional(enum_param_list))
+
+enum_member_param_name = kw("virtual")
+enum_member_param = P.Group(enum_member_param_name  - s('=') - any_type)
+enum_member_param_list = P.Forward()
+enum_member_param_list << enum_member_param + P.Optional(s(',') + P.Optional(enum_member_param_list))
+
+enum_member = P.Group(identifier - P.Group(P.Optional(s('(') - enum_member_param_list - s(')'))) - s('=') + integer)
 enum_list = P.Forward()
 enum_list << enum_member + P.Optional(s(',') + P.Optional(enum_list))
-enum = kw('enum') - identifier - s('{') + \
+enum = kw('enum') - identifier - P.Group(P.Optional(s('(') - enum_param_list - s(')'))) - s('{') + \
          P.Group(P.Optional(enum_list)) + \
          s('}') - s(';')
 
diff --git a/loxi_ir.py b/loxi_ir.py
index 9a27272..8f1e822 100644
--- a/loxi_ir.py
+++ b/loxi_ir.py
@@ -39,6 +39,7 @@
     'OFFieldLengthMember',
     'OFPadMember',
     'OFEnum',
+    'OFEnumEntry'
 ]
 
 """
@@ -131,6 +132,13 @@
 All values are Python ints.
 
 @param name
-@param values List of (name, value) tuples in input order
+@param entries List of OFEnumEntry objects in input order
+@params dict of optional params. Currently defined:
+       - wire_type: the low_level type of the enum values (uint8,...)
 """
-OFEnum = namedtuple('OFEnum', ['name', 'values'])
+class OFEnum(namedtuple('OFEnum', ['name', 'entries', 'params'])):
+    @property
+    def values(self):
+        return [(e.name, e.value) for e in self.entries]
+
+OFEnumEntry = namedtuple('OFEnumEntry', ['name', 'value', 'params'])
diff --git a/loxigen.py b/loxigen.py
index 36d6872..92204ca 100755
--- a/loxigen.py
+++ b/loxigen.py
@@ -451,10 +451,10 @@
                 versions[version_name]['classes'][ofclass.name] = legacy_members
 
             for enum in ofinput.enums:
-                for name, value in enum.values:
+                for entry in enum.entries:
                     identifiers.add_identifier(
-                        translation.loxi_name(name),
-                        name, enum.name, value, wire_version,
+                        translation.loxi_name(entry.name),
+                        entry.name, enum.name, entry.value, wire_version,
                         of_g.identifiers, of_g.identifiers_by_group)
 
         for wire_version, ofinputs in ofinputs_by_version.items():
diff --git a/openflow_input/bsn_vport b/openflow_input/bsn_vport
index 0cf30bf..03b4b43 100644
--- a/openflow_input/bsn_vport
+++ b/openflow_input/bsn_vport
@@ -38,7 +38,7 @@
 // When the ingress or egress VID has this value, no outer tag should be used.
 // In this case, the corresponding TPID is ignored.
 
-enum ofp_bsn_vport_q_in_q_untagged {
+enum ofp_bsn_vport_q_in_q_untagged(wire_type=uint16_t, complete=False) {
     OF_BSN_VPORT_Q_IN_Q_UNTAGGED = 0xffff,
 };
 
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index e9cb6f0..ceb2016 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -61,7 +61,7 @@
     OFPQ_MIN_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -86,7 +86,7 @@
     OFPT_QUEUE_GET_CONFIG_REPLY = 21,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_STP = 0x2,
     OFPPC_NO_RECV = 0x4,
@@ -96,16 +96,19 @@
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_STP_LISTEN = 0,
     OFPPS_LINK_DOWN = 1,
     OFPPS_STP_LEARN = 0x100,
     OFPPS_STP_FORWARD = 0x200,
     OFPPS_STP_BLOCK = 0x300,
-    OFPPS_STP_MASK = 0x300,
+    OFPPS_STP_MASK(virtual=True) = 0x300,
 };
 
-enum ofp_port {
+// FIXME: these constants are currently 32 bit due to implementation
+// details of loci, which is in violation of the OpenFlow spec.
+// Should recast to 32 bits and fix/glue the c backend
+enum ofp_port(wire_type=uint16_t, complete=False) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -117,7 +120,7 @@
     OFPP_NONE = 0xffffffff,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -132,12 +135,12 @@
     OFPPF_PAUSE_ASYM = 0x800,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint32_t) {
     OFPQT_NONE = 0,
     OFPQT_MIN_RATE = 1,
 };
 
-enum ofp_flow_wildcards {
+enum ofp_flow_wildcards(wire_type=uint32_t, bitmask=True) {
     OFPFW_IN_PORT = 0x1,
     OFPFW_DL_VLAN = 0x2,
     OFPFW_DL_SRC = 0x4,
@@ -159,7 +162,7 @@
     OFPFW_ALL = 0x3fffff,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_SET_VLAN_VID = 1,
     OFPAT_SET_VLAN_PCP = 2,
@@ -175,7 +178,7 @@
     OFPAT_VENDOR = 0xffff,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -186,14 +189,14 @@
     OFPC_ARP_MATCH_IP = 0x80,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint32_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0x0,
     OFPC_FRAG_DROP = 0x1,
     OFPC_FRAG_REASM = 0x2,
     OFPC_FRAG_MASK = 0x3,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint16_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -201,17 +204,17 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
     OFPFF_EMERG = 0x4,
 };
 
-enum ofp_stats_reply_flags {
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
 
-enum ofp_stats_types {
+enum ofp_stats_types(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -221,24 +224,24 @@
     OFPST_VENDOR = 0xffff,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -247,12 +250,12 @@
     OFPET_QUEUE_OP_FAILED = 5,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
@@ -264,7 +267,7 @@
     OFPBRC_BUFFER_UNKNOWN = 8,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_VENDOR = 2,
@@ -276,7 +279,7 @@
     OFPBAC_BAD_QUEUE = 8,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_ALL_TABLES_FULL = 0,
     OFPFMFC_OVERLAP = 1,
     OFPFMFC_EPERM = 2,
@@ -285,12 +288,12 @@
     OFPFMFC_UNSUPPORTED = 5,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index 553e665..18faaa8 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -63,7 +63,7 @@
     OFPQ_MIN_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_port {
+enum ofp_port(wire_type=uint32_t) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -74,11 +74,11 @@
     OFPP_LOCAL = 0xfffffffe,
 };
 
-enum ofp_port_no {
+enum ofp_port_no(wire_type=uint32_t, complete=no) {
     OFPP_ANY = 0xffffffff,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -105,22 +105,22 @@
     OFPT_QUEUE_GET_CONFIG_REPLY = 23,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint16_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0,
     OFPC_FRAG_DROP = 1,
     OFPC_FRAG_REASM = 2,
-    OFPC_FRAG_MASK = 3,
+    OFPC_FRAG_MASK(virtual=True) = 3,
     OFPC_INVALID_TTL_TO_CONTROLLER = 4,
 };
 
-enum ofp_table_config {
+enum ofp_table_config(wire_type=uint32_t, bitmask=True) {
     OFPTC_TABLE_MISS_CONTROLLER = 0,
     OFPTC_TABLE_MISS_CONTINUE = 1,
     OFPTC_TABLE_MISS_DROP = 2,
-    OFPTC_TABLE_MISS_MASK = 3,
+    OFPTC_TABLE_MISS_MASK(virtual=True) = 3,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -130,20 +130,20 @@
     OFPC_ARP_MATCH_IP = 0x80,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_LINK_DOWN = 0x1,
     OFPPS_BLOCKED = 0x2,
     OFPPS_LIVE = 0x4,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -162,18 +162,18 @@
     OFPPF_PAUSE_ASYM = 0x8000,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_SET_VLAN_VID = 1,
     OFPAT_SET_VLAN_PCP = 2,
@@ -202,7 +202,7 @@
     OFPAT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint8_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -210,13 +210,13 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_group_mod_command {
+enum ofp_group_mod_command(wire_type=uint16_t) {
     OFPGC_ADD = 0,
     OFPGC_MODIFY = 1,
     OFPGC_DELETE = 2,
 };
 
-enum ofp_flow_wildcards {
+enum ofp_flow_wildcards(wire_type=uint32_t, bitmask=True) {
     OFPFW_IN_PORT = 0x1,
     OFPFW_DL_VLAN = 0x2,
     OFPFW_DL_VLAN_PCP = 0x4,
@@ -227,19 +227,19 @@
     OFPFW_TP_DST = 0x80,
     OFPFW_MPLS_LABEL = 0x100,
     OFPFW_MPLS_TC = 0x200,
-    OFPFW_ALL = 0x3ff,
+    OFPFW_ALL(virtual=True) = 0x3ff,
 };
 
-enum ofp_vlan_id {
+enum ofp_vlan_id(wire_type=uint16_t) {
     OFPVID_ANY = 0xfffe,
     OFPVID_NONE = 0xffff,
 };
 
-enum ofp_match_type {
+enum ofp_match_type(wire_type=uint16_t) {
     OFPMT_STANDARD = 0,
 };
 
-enum ofp_instruction_type {
+enum ofp_instruction_type(wire_type=uint16_t, bitmask=True) {
     OFPIT_GOTO_TABLE = 0x1,
     OFPIT_WRITE_METADATA = 0x2,
     OFPIT_WRITE_ACTIONS = 0x3,
@@ -248,32 +248,32 @@
     OFPIT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
 };
 
-enum ofp_group {
+enum ofp_group(wire_type=uint32_t, complete=False) {
     OFPG_MAX = 0xffffff00,
     OFPG_ALL = 0xfffffffc,
     OFPG_ANY = 0xffffffff,
 };
 
-enum ofp_group_type {
+enum ofp_group_type(wire_type=uint8_t) {
     OFPGT_ALL = 0,
     OFPGT_SELECT = 1,
     OFPGT_INDIRECT = 2,
     OFPGT_FF = 3,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
     OFPRR_GROUP_DELETE = 3,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -287,12 +287,12 @@
     OFPET_SWITCH_CONFIG_FAILED = 10,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
@@ -305,7 +305,7 @@
     OFPBRC_BAD_TABLE_ID = 9,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
@@ -321,7 +321,7 @@
     OFPBAC_BAD_TAG = 12,
 };
 
-enum ofp_bad_instruction_code {
+enum ofp_bad_instruction_code(wire_type=uint16_t) {
     OFPBIC_UNKNOWN_INST = 0,
     OFPBIC_UNSUP_INST = 1,
     OFPBIC_BAD_TABLE_ID = 2,
@@ -330,7 +330,7 @@
     OFPBIC_UNSUP_EXP_INST = 5,
 };
 
-enum ofp_bad_match_code {
+enum ofp_bad_match_code(wire_type=uint16_t) {
     OFPBMC_BAD_TYPE = 0,
     OFPBMC_BAD_LEN = 1,
     OFPBMC_BAD_TAG = 2,
@@ -341,7 +341,7 @@
     OFPBMC_BAD_VALUE = 7,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_UNKNOWN = 0,
     OFPFMFC_TABLE_FULL = 1,
     OFPFMFC_BAD_TABLE_ID = 2,
@@ -351,7 +351,7 @@
     OFPFMFC_BAD_COMMAND = 6,
 };
 
-enum ofp_group_mod_failed_code {
+enum ofp_group_mod_failed_code(wire_type=uint16_t) {
     OFPGMFC_GROUP_EXISTS = 0,
     OFPGMFC_INVALID_GROUP = 1,
     OFPGMFC_WEIGHT_UNSUPPORTED = 2,
@@ -363,30 +363,30 @@
     OFPGMFC_UNKNOWN_GROUP = 8,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
     OFPPMFC_BAD_CONFIG = 2,
     OFPPMFC_BAD_ADVERTISE = 3,
 };
 
-enum ofp_table_mod_failed_code {
+enum ofp_table_mod_failed_code(wire_type=uint16_t) {
     OFPTMFC_BAD_TABLE = 0,
     OFPTMFC_BAD_CONFIG = 1,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
 };
 
-enum ofp_switch_config_failed_code {
+enum ofp_switch_config_failed_code(wire_type=uint16_t) {
     OFPSCFC_BAD_FLAGS = 0,
     OFPSCFC_BAD_LEN = 1,
 };
 
-enum ofp_stats_types {
+enum ofp_stats_types(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -398,11 +398,11 @@
     OFPST_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_stats_reply_flags {
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint16_t) {
     OFPQT_NONE = 0,
     OFPQT_MIN_RATE = 1,
 };
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 8b4fa3f..f4d31d6 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -59,7 +59,7 @@
     OFPQ_MAX_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_port {
+enum ofp_port(wire_type=uint32_t) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -70,11 +70,11 @@
     OFPP_LOCAL = 0xfffffffe,
 };
 
-enum ofp_port_no {
+enum ofp_port_no(wire_type=uint32_t, complete=no) {
     OFPP_ANY = 0xffffffff,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -103,7 +103,7 @@
     OFPT_ROLE_REPLY = 25,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint16_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0,
     OFPC_FRAG_DROP = 1,
     OFPC_FRAG_REASM = 2,
@@ -111,19 +111,19 @@
     OFPC_INVALID_TTL_TO_CONTROLLER = 4,
 };
 
-enum ofp_table_config {
+enum ofp_table_config(wire_type=uint32_t, bitmask=True) {
     OFPTC_TABLE_MISS_CONTROLLER = 0,
     OFPTC_TABLE_MISS_CONTINUE = 1,
     OFPTC_TABLE_MISS_DROP = 2,
     OFPTC_TABLE_MISS_MASK = 3,
 };
 
-enum ofp_table {
+enum ofp_table(wire_type=uint8_t, complete=False) {
     OFPTT_MAX = 0xfe,
     OFPTT_ALL = 0xff,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -133,20 +133,20 @@
     OFPC_PORT_BLOCKED = 0x100,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_LINK_DOWN = 0x1,
     OFPPS_BLOCKED = 0x2,
     OFPPS_LIVE = 0x4,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -165,30 +165,30 @@
     OFPPF_PAUSE_ASYM = 0x8000,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_match_type {
+enum ofp_match_type(wire_type=uint16_t) {
     OFPMT_STANDARD = 0,
     OFPMT_OXM = 1,
 };
 
-enum ofp_oxm_class {
+enum ofp_oxm_class(wire_type=uint16_t) {
     OFPXMC_NXM_0 = 0,
     OFPXMC_NXM_1 = 1,
     OFPXMC_OPENFLOW_BASIC = 0x8000,
     OFPXMC_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_vlan_id {
+enum ofp_vlan_id(wire_type=uint16_t) {
     OFPVID_NONE = 0,
     OFPVID_PRESENT = 0x1000,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_COPY_TTL_OUT = 0xb,
     OFPAT_COPY_TTL_IN = 0xc,
@@ -206,12 +206,12 @@
     OFPAT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_max_len {
+enum ofp_controller_max_len(wire_type=uint16_t, complete=False) {
     OFPCML_MAX = 0xffe5,
     OFPCML_NO_BUFFER = 0xffff,
 };
 
-enum ofp_instruction_type {
+enum ofp_instruction_type(wire_type=uint16_t, bitmask=True) {
     OFPIT_GOTO_TABLE = 0x1,
     OFPIT_WRITE_METADATA = 0x2,
     OFPIT_WRITE_ACTIONS = 0x3,
@@ -220,7 +220,7 @@
     OFPIT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint8_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -228,45 +228,45 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
     OFPFF_RESET_COUNTS = 0x4,
 };
 
-enum ofp_group {
+enum ofp_group(wire_type=uint32_t, complete=False) {
     OFPG_MAX = 0xffffff00,
     OFPG_ALL = 0xfffffffc,
     OFPG_ANY = 0xffffffff,
 };
 
-enum ofp_group_mod_command {
+enum ofp_group_mod_command(wire_type=uint16_t) {
     OFPGC_ADD = 0,
     OFPGC_MODIFY = 1,
     OFPGC_DELETE = 2,
 };
 
-enum ofp_group_type {
+enum ofp_group_type(wire_type=uint8_t) {
     OFPGT_ALL = 0,
     OFPGT_SELECT = 1,
     OFPGT_INDIRECT = 2,
     OFPGT_FF = 3,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
     OFPR_INVALID_TTL = 2,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
     OFPRR_GROUP_DELETE = 3,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -282,12 +282,12 @@
     OFPET_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
@@ -303,7 +303,7 @@
     OFPBRC_BAD_PACKET = 12,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
@@ -322,7 +322,7 @@
     OFPBAC_BAD_SET_ARGUMENT = 15,
 };
 
-enum ofp_bad_instruction_code {
+enum ofp_bad_instruction_code(wire_type=uint16_t) {
     OFPBIC_UNKNOWN_INST = 0,
     OFPBIC_UNSUP_INST = 1,
     OFPBIC_BAD_TABLE_ID = 2,
@@ -334,7 +334,7 @@
     OFPBIC_EPERM = 8,
 };
 
-enum ofp_bad_match_code {
+enum ofp_bad_match_code(wire_type=uint16_t) {
     OFPBMC_BAD_TYPE = 0,
     OFPBMC_BAD_LEN = 1,
     OFPBMC_BAD_TAG = 2,
@@ -349,7 +349,7 @@
     OFPBMC_EPERM = 11,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_UNKNOWN = 0,
     OFPFMFC_TABLE_FULL = 1,
     OFPFMFC_BAD_TABLE_ID = 2,
@@ -360,7 +360,7 @@
     OFPFMFC_BAD_FLAGS = 7,
 };
 
-enum ofp_group_mod_failed_code {
+enum ofp_group_mod_failed_code(wire_type=uint16_t) {
     OFPGMFC_GROUP_EXISTS = 0,
     OFPGMFC_INVALID_GROUP = 1,
     OFPGMFC_WEIGHT_UNSUPPORTED = 2,
@@ -378,7 +378,7 @@
     OFPGMFC_EPERM = 14,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
     OFPPMFC_BAD_CONFIG = 2,
@@ -386,31 +386,31 @@
     OFPPMFC_EPERM = 4,
 };
 
-enum ofp_table_mod_failed_code {
+enum ofp_table_mod_failed_code(wire_type=uint16_t) {
     OFPTMFC_BAD_TABLE = 0,
     OFPTMFC_BAD_CONFIG = 1,
     OFPTMFC_EPERM = 2,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
 };
 
-enum ofp_switch_config_failed_code {
+enum ofp_switch_config_failed_code(wire_type=uint16_t) {
     OFPSCFC_BAD_FLAGS = 0,
     OFPSCFC_BAD_LEN = 1,
     OFPSCFC_EPERM = 2,
 };
 
-enum ofp_role_request_failed_code {
+enum ofp_role_request_failed_code (wire_type=uint16_t){
     OFPRRFC_STALE = 0,
     OFPRRFC_UNSUP = 1,
     OFPRRFC_BAD_ROLE = 2,
 };
 
-enum ofp_stats_types {
+enum ofp_stats_types(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -423,24 +423,24 @@
     OFPST_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_stats_reply_flags {
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
 
-enum ofp_group_capabilities {
+enum ofp_group_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPGFC_SELECT_WEIGHT = 0x1,
     OFPGFC_SELECT_LIVENESS = 0x2,
     OFPGFC_CHAINING = 0x4,
     OFPGFC_CHAINING_CHECKS = 0x8,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint16_t) {
     OFPQT_MIN_RATE = 0x1,
     OFPQT_MAX_RATE = 0x2,
     OFPQT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_role {
+enum ofp_controller_role(wire_type=uint32_t) {
     OFPCR_ROLE_NOCHANGE = 0,
     OFPCR_ROLE_EQUAL = 1,
     OFPCR_ROLE_MASTER = 2,
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index 0d5cec3..b0aa242 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -58,11 +58,11 @@
     OFPQ_MIN_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_port_no {
+enum ofp_port_no(wire_type=uint32_t, complete=no) {
     OFPP_ANY = 0xffffffff,
 };
 
-enum ofp_port {
+enum ofp_port(wire_type=uint32_t) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -73,7 +73,7 @@
     OFPP_LOCAL = 0xfffffffe,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -106,23 +106,23 @@
     OFPT_METER_MOD = 29,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint16_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0,
     OFPC_FRAG_DROP = 1,
     OFPC_FRAG_REASM = 2,
     OFPC_FRAG_MASK = 3,
 };
 
-enum ofp_table_config {
+enum ofp_table_config(wire_type=uint32_t, bitmask=True) {
     OFPTC_DEPRECATED_MASK = 0x3,
 };
 
-enum ofp_table {
+enum ofp_table(wire_type=uint8_t, complete=False) {
     OFPTT_MAX = 0xfe,
     OFPTT_ALL = 0xff,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -132,20 +132,20 @@
     OFPC_PORT_BLOCKED = 0x100,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_LINK_DOWN = 0x1,
     OFPPS_BLOCKED = 0x2,
     OFPPS_LIVE = 0x4,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -164,30 +164,32 @@
     OFPPF_PAUSE_ASYM = 0x8000,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_match_type {
+enum ofp_match_type(wire_type=uint16_t) {
     OFPMT_STANDARD = 0,
     OFPMT_OXM = 1,
 };
 
-enum ofp_oxm_class {
+enum ofp_oxm_class(wire_type=uint16_t) {
     OFPXMC_NXM_0 = 0,
     OFPXMC_NXM_1 = 1,
     OFPXMC_OPENFLOW_BASIC = 0x8000,
     OFPXMC_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_vlan_id {
+enum ofp_vlan_id(wire_type=uint16_t) {
     OFPVID_NONE = 0,
     OFPVID_PRESENT = 0x1000,
 };
 
-enum ofp_ipv6exthdr_flags {
+// FIXME: OF spec specified this as '9' bits, implicitly adding
+// to full byte
+enum ofp_ipv6exthdr_flags(wire_type=uint16_t, bitmask=True) {
     OFPIEH_NONEXT = 0x1,
     OFPIEH_ESP = 0x2,
     OFPIEH_AUTH = 0x4,
@@ -199,7 +201,7 @@
     OFPIEH_UNSEQ = 0x100,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_COPY_TTL_OUT = 0xb,
     OFPAT_COPY_TTL_IN = 0xc,
@@ -219,12 +221,12 @@
     OFPAT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_max_len {
+enum ofp_controller_max_len(wire_type=uint16_t, complete=False) {
     OFPCML_MAX = 0xffe5,
     OFPCML_NO_BUFFER = 0xffff,
 };
 
-enum ofp_instruction_type {
+enum ofp_instruction_type(wire_type=uint16_t, bitmask=True) {
     OFPIT_GOTO_TABLE = 0x1,
     OFPIT_WRITE_METADATA = 0x2,
     OFPIT_WRITE_ACTIONS = 0x3,
@@ -234,7 +236,7 @@
     OFPIT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint8_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -242,7 +244,7 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
     OFPFF_RESET_COUNTS = 0x4,
@@ -250,65 +252,65 @@
     OFPFF_NO_BYT_COUNTS = 0x10,
 };
 
-enum ofp_group {
+enum ofp_group(wire_type=uint32_t, complete=False) {
     OFPG_MAX = 0xffffff00,
     OFPG_ALL = 0xfffffffc,
     OFPG_ANY = 0xffffffff,
 };
 
-enum ofp_group_mod_command {
+enum ofp_group_mod_command(wire_type=uint16_t) {
     OFPGC_ADD = 0,
     OFPGC_MODIFY = 1,
     OFPGC_DELETE = 2,
 };
 
-enum ofp_group_type {
+enum ofp_group_type(wire_type=uint8_t) {
     OFPGT_ALL = 0,
     OFPGT_SELECT = 1,
     OFPGT_INDIRECT = 2,
     OFPGT_FF = 3,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
     OFPR_INVALID_TTL = 2,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
     OFPRR_GROUP_DELETE = 3,
 };
 
-enum ofp_meter {
+enum ofp_meter(wire_type=uint32_t, complete=False) {
     OFPM_MAX = 0xffff0000,
     OFPM_SLOWPATH = 0xfffffffd,
     OFPM_CONTROLLER = 0xfffffffe,
     OFPM_ALL = 0xffffffff,
 };
 
-enum ofp_meter_band_type {
+enum ofp_meter_band_type(wire_type=uint16_t) {
     OFPMBT_DROP = 0x1,
     OFPMBT_DSCP_REMARK = 0x2,
     OFPMBT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_meter_mod_command {
+enum ofp_meter_mod_command(wire_type=uint16_t) {
     OFPMC_ADD = 0,
     OFPMC_MODIFY = 1,
     OFPMC_DELETE = 2,
 };
 
-enum ofp_meter_flags {
+enum ofp_meter_flags(wire_type=uint16_t, bitmask=True) {
     OFPMF_KBPS = 0x1,
     OFPMF_PKTPS = 0x2,
     OFPMF_BURST = 0x4,
     OFPMF_STATS = 0x8,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -326,12 +328,12 @@
     OFPET_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_MULTIPART = 2,
@@ -348,7 +350,7 @@
     OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
@@ -367,7 +369,7 @@
     OFPBAC_BAD_SET_ARGUMENT = 15,
 };
 
-enum ofp_bad_instruction_code {
+enum ofp_bad_instruction_code(wire_type=uint16_t) {
     OFPBIC_UNKNOWN_INST = 0,
     OFPBIC_UNSUP_INST = 1,
     OFPBIC_BAD_TABLE_ID = 2,
@@ -379,7 +381,7 @@
     OFPBIC_EPERM = 8,
 };
 
-enum ofp_bad_match_code {
+enum ofp_bad_match_code(wire_type=uint16_t) {
     OFPBMC_BAD_TYPE = 0,
     OFPBMC_BAD_LEN = 1,
     OFPBMC_BAD_TAG = 2,
@@ -394,7 +396,7 @@
     OFPBMC_EPERM = 11,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_UNKNOWN = 0,
     OFPFMFC_TABLE_FULL = 1,
     OFPFMFC_BAD_TABLE_ID = 2,
@@ -405,7 +407,7 @@
     OFPFMFC_BAD_FLAGS = 7,
 };
 
-enum ofp_group_mod_failed_code {
+enum ofp_group_mod_failed_code(wire_type=uint16_t) {
     OFPGMFC_GROUP_EXISTS = 0,
     OFPGMFC_INVALID_GROUP = 1,
     OFPGMFC_WEIGHT_UNSUPPORTED = 2,
@@ -423,7 +425,7 @@
     OFPGMFC_EPERM = 14,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
     OFPPMFC_BAD_CONFIG = 2,
@@ -431,31 +433,31 @@
     OFPPMFC_EPERM = 4,
 };
 
-enum ofp_table_mod_failed_code {
+enum ofp_table_mod_failed_code(wire_type=uint16_t) {
     OFPTMFC_BAD_TABLE = 0,
     OFPTMFC_BAD_CONFIG = 1,
     OFPTMFC_EPERM = 2,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
 };
 
-enum ofp_switch_config_failed_code {
+enum ofp_switch_config_failed_code(wire_type=uint16_t) {
     OFPSCFC_BAD_FLAGS = 0,
     OFPSCFC_BAD_LEN = 1,
     OFPSCFC_EPERM = 2,
 };
 
-enum ofp_role_request_failed_code {
+enum ofp_role_request_failed_code(wire_type=uint16_t){
     OFPRRFC_STALE = 0,
     OFPRRFC_UNSUP = 1,
     OFPRRFC_BAD_ROLE = 2,
 };
 
-enum ofp_meter_mod_failed_code {
+enum ofp_meter_mod_failed_code(wire_type=uint16_t) {
     OFPMMFC_UNKNOWN = 0,
     OFPMMFC_METER_EXISTS = 1,
     OFPMMFC_INVALID_METER = 2,
@@ -470,7 +472,7 @@
     OFPMMFC_OUT_OF_BANDS = 11,
 };
 
-enum ofp_table_features_failed_code {
+enum ofp_table_features_failed_code(wire_type=uint16_t) {
     OFPTFFC_BAD_TABLE = 0,
     OFPTFFC_BAD_METADATA = 1,
     OFPTFFC_BAD_TYPE = 2,
@@ -479,7 +481,7 @@
     OFPTFFC_EPERM = 5,
 };
 
-enum ofp_multipart_types {
+enum ofp_multipart_types(wire_type=uint16_t) {
     OFPMP_DESC = 0,
     OFPMP_FLOW = 1,
     OFPMP_AGGREGATE = 2,
@@ -497,15 +499,15 @@
     OFPMP_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_multipart_request_flags {
+enum ofp_multipart_request_flags(wire_type=uint16_t, bitmask=True) {
     OFPMPF_REQ_MORE = 0x1,
 };
 
-enum ofp_multipart_reply_flags {
+enum ofp_multipart_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPMPF_REPLY_MORE = 0x1,
 };
 
-enum ofp_table_feature_prop_type {
+enum ofp_table_feature_prop_type(wire_type=uint16_t) {
     OFPTFPT_INSTRUCTIONS = 0,
     OFPTFPT_INSTRUCTIONS_MISS = 1,
     OFPTFPT_NEXT_TABLES = 2,
@@ -524,27 +526,27 @@
     OFPTFPT_EXPERIMENTER_MISS = 0xffff,
 };
 
-enum ofp_group_capabilities {
+enum ofp_group_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPGFC_SELECT_WEIGHT = 0x1,
     OFPGFC_SELECT_LIVENESS = 0x2,
     OFPGFC_CHAINING = 0x4,
     OFPGFC_CHAINING_CHECKS = 0x8,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint16_t) {
     OFPQT_MIN_RATE = 0x1,
     OFPQT_MAX_RATE = 0x2,
     OFPQT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_role {
+enum ofp_controller_role(wire_type=uint32_t) {
     OFPCR_ROLE_NOCHANGE = 0,
     OFPCR_ROLE_EQUAL = 1,
     OFPCR_ROLE_MASTER = 2,
     OFPCR_ROLE_SLAVE = 3,
 };
 
-enum ofp_hello_elem_type {
+enum ofp_hello_elem_type(wire_type=uint16_t) {
     OFPHET_VERSIONBITMAP = 1,
 };
 
diff --git a/test_data/__init__.py b/test_data/__init__.py
index f21770b..7a55c11 100644
--- a/test_data/__init__.py
+++ b/test_data/__init__.py
@@ -45,6 +45,9 @@
                 result.append(dirname + '/' + filename)
     return sorted(result)
 
+def exists(name):
+    return os.path.exists(os.path.join(_test_data_dir, name))
+
 def read(name):
     """
     Read, parse, and return a test data file
diff --git a/test_data/of10/action_bsn_set_tunnel_dst.data b/test_data/of10/action_bsn_set_tunnel_dst.data
index 7e1f43d..7a5747c 100644
--- a/test_data/of10/action_bsn_set_tunnel_dst.data
+++ b/test_data/of10/action_bsn_set_tunnel_dst.data
@@ -8,3 +8,6 @@
 ofp.action.bsn_set_tunnel_dst(dst=0x12345678)
 -- python pretty-printer
 bsn_set_tunnel_dst { dst = 0x12345678 }
+-- c
+obj = of_action_bsn_set_tunnel_dst_new(OF_VERSION_1_0);
+of_action_bsn_set_tunnel_dst_dst_set(obj, 0x12345678);
diff --git a/test_data/of10/desc_stats_reply.data b/test_data/of10/desc_stats_reply.data
index b4b3eb1..c000bb0 100644
--- a/test_data/of10/desc_stats_reply.data
+++ b/test_data/of10/desc_stats_reply.data
@@ -145,3 +145,27 @@
     sw_desc="Indigo-2 LRI pre-release",
     serial_num="11235813213455",
     dp_desc="Indigo-2 LRI forwarding module")
+-- c
+obj = of_desc_stats_reply_new(OF_VERSION_1_0);
+of_desc_stats_reply_xid_set(obj, 3);
+of_desc_stats_reply_flags_set(obj, OF_STATS_REPLY_FLAG_REPLY_MORE);
+{
+    of_desc_str_t mfr_desc = "The Indigo-2 Community";
+    of_desc_stats_reply_mfr_desc_set(obj, mfr_desc);
+}
+{
+    of_desc_str_t hw_desc = "Unknown server";
+    of_desc_stats_reply_hw_desc_set(obj, hw_desc);
+}
+{
+    of_desc_str_t sw_desc = "Indigo-2 LRI pre-release";
+    of_desc_stats_reply_sw_desc_set(obj, sw_desc);
+}
+{
+    of_desc_str_t dp_desc = "Indigo-2 LRI forwarding module";
+    of_desc_stats_reply_dp_desc_set(obj, dp_desc);
+}
+{
+    of_serial_num_t serial_num = "11235813213455";
+    of_desc_stats_reply_serial_num_set(obj, serial_num);
+}
diff --git a/test_data/of10/echo_request.data b/test_data/of10/echo_request.data
index abe06fc..701376e 100644
--- a/test_data/of10/echo_request.data
+++ b/test_data/of10/echo_request.data
@@ -7,3 +7,10 @@
 ofp.message.echo_request(xid=0x12345678, data="ab\x01")
 -- python pretty-printer
 echo_request { xid = 0x12345678, data = 'ab\x01' }
+-- c
+obj = of_echo_request_new(OF_VERSION_1_0);
+of_echo_request_xid_set(obj, 0x12345678);
+{
+    of_octets_t data = { .data=(uint8_t *)"ab\x01", .bytes=3 };
+    of_echo_request_data_set(obj, &data);
+}
diff --git a/test_data/of10/flow_add.data b/test_data/of10/flow_add.data
index 9801a36..fc09a23 100644
--- a/test_data/of10/flow_add.data
+++ b/test_data/of10/flow_add.data
@@ -1,6 +1,6 @@
 -- binary
 01 0e 00 70 12 34 56 78
-00 00 00 0c 00 03 01 23
+00 10 00 02 00 03 01 23
 45 67 89 ab cd ef 01 23
 45 67 00 00 00 00 00 00
 00 00 00 00 c0 a8 03 7f
@@ -17,7 +17,7 @@
 ofp.message.flow_add(
     xid=0x12345678,
     match=ofp.match(
-        wildcards=ofp.OFPFW_DL_SRC|ofp.OFPFW_DL_DST,
+        wildcards=ofp.OFPFW_DL_VLAN|ofp.OFPFW_DL_VLAN_PCP,
         in_port=3,
         ipv4_src=0xc0a8037f,
         ipv4_dst=0xffffffff,
@@ -33,7 +33,7 @@
 flow_add {
   xid = 0x12345678,
   match = match_v1 {
-    wildcards = OFPFW_DL_SRC|OFPFW_DL_DST,
+    wildcards = OFPFW_DL_VLAN|OFPFW_DL_VLAN_PCP,
     in_port = 3,
     eth_src = 01:23:45:67:89:ab,
     eth_dst = cd:ef:01:23:45:67,
@@ -60,3 +60,49 @@
     bsn_set_tunnel_dst { dst = 0x0 }
   ]
 }
+-- c
+obj = of_flow_add_new(OF_VERSION_1_0);
+of_flow_add_xid_set(obj, 0x12345678);
+of_flow_add_idle_timeout_set(obj, 5);
+of_flow_add_flags_set(obj, 2);
+{
+    of_match_t match = { OF_VERSION_1_0 };
+    match.fields.in_port = 3;
+    match.fields.eth_src = (of_mac_addr_t) { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } };
+    match.fields.eth_dst = (of_mac_addr_t) { { 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 } };
+    match.fields.ipv4_src = 0xc0a8037f;
+    match.fields.ipv4_dst = 0xffffffff;
+    OF_MATCH_MASK_IN_PORT_EXACT_SET(&match);
+    OF_MATCH_MASK_ETH_SRC_EXACT_SET(&match);
+    OF_MATCH_MASK_ETH_DST_EXACT_SET(&match);
+    //OF_MATCH_MASK_VLAN_VID_EXACT_SET(&match);
+    //OF_MATCH_MASK_VLAN_PCP_EXACT_SET(&match);
+    OF_MATCH_MASK_ETH_TYPE_EXACT_SET(&match);
+    OF_MATCH_MASK_IP_DSCP_EXACT_SET(&match);
+    OF_MATCH_MASK_IP_PROTO_EXACT_SET(&match);
+    OF_MATCH_MASK_IPV4_SRC_EXACT_SET(&match);
+    OF_MATCH_MASK_IPV4_DST_EXACT_SET(&match);
+    OF_MATCH_MASK_TCP_SRC_EXACT_SET(&match);
+    OF_MATCH_MASK_TCP_DST_EXACT_SET(&match);
+    of_flow_add_match_set(obj, &match);
+}
+{
+    of_list_action_t actions;
+    of_flow_add_actions_bind(obj, &actions);
+    {
+        of_action_t action;
+        of_action_output_init(&action.output, OF_VERSION_1_0, -1, 1);
+        of_list_action_append_bind(&actions, &action);
+        of_action_output_port_set(&action.output, OF_PORT_DEST_FLOOD);
+    }
+    {
+        of_action_t action;
+        of_action_nicira_dec_ttl_init(&action.nicira_dec_ttl, OF_VERSION_1_0, -1, 1);
+        of_list_action_append_bind(&actions, &action);
+    }
+    {
+        of_action_t action;
+        of_action_bsn_set_tunnel_dst_init(&action.bsn_set_tunnel_dst, OF_VERSION_1_0, -1, 1);
+        of_list_action_append_bind(&actions, &action);
+    }
+}
diff --git a/test_data/of10/flow_stats_entry.data b/test_data/of10/flow_stats_entry.data
index 45c6569..2f9df64 100644
--- a/test_data/of10/flow_stats_entry.data
+++ b/test_data/of10/flow_stats_entry.data
@@ -40,3 +40,36 @@
     actions=[
         ofp.action.output(port=1),
         ofp.action.output(port=2)])
+-- c
+obj = of_flow_stats_entry_new(OF_VERSION_1_0);
+{
+    of_object_t list;
+    of_flow_stats_entry_actions_bind(obj, &list);
+    {
+        of_object_t *obj = of_action_output_new(OF_VERSION_1_0);
+        of_action_output_max_len_set(obj, 0);
+        of_action_output_port_set(obj, 1);
+        of_list_append(&list, obj);
+        of_object_delete(obj);
+    }
+    {
+        of_object_t *obj = of_action_output_new(OF_VERSION_1_0);
+        of_action_output_max_len_set(obj, 0);
+        of_action_output_port_set(obj, 2);
+        of_list_append(&list, obj);
+        of_object_delete(obj);
+    }
+}
+of_flow_stats_entry_byte_count_set(obj, 1000);
+of_flow_stats_entry_cookie_set(obj, 81985529216486895);
+of_flow_stats_entry_duration_nsec_set(obj, 2);
+of_flow_stats_entry_duration_sec_set(obj, 1);
+of_flow_stats_entry_hard_timeout_set(obj, 10);
+of_flow_stats_entry_idle_timeout_set(obj, 5);
+{
+    of_match_t match = { OF_VERSION_1_0 };
+    of_flow_stats_entry_match_set(obj, &match);
+}
+of_flow_stats_entry_packet_count_set(obj, 10);
+of_flow_stats_entry_priority_set(obj, 100);
+of_flow_stats_entry_table_id_set(obj, 3);
diff --git a/test_data/of10/flow_stats_reply.data b/test_data/of10/flow_stats_reply.data
index 38db4d5..185235b 100644
--- a/test_data/of10/flow_stats_reply.data
+++ b/test_data/of10/flow_stats_reply.data
@@ -90,3 +90,93 @@
             actions=[ofp.action.output(port=1),
             ofp.action.output(port=2),
             ofp.action.output(port=3)])])
+-- c
+obj = of_flow_stats_reply_new(OF_VERSION_1_0);
+of_flow_stats_reply_flags_set(obj, 0);
+of_flow_stats_reply_xid_set(obj, 6);
+{
+    of_object_t *entries = of_list_flow_stats_entry_new(OF_VERSION_1_0);
+    {
+        of_object_t *elem = of_flow_stats_entry_new(OF_VERSION_1_0);
+        of_flow_stats_entry_byte_count_set(elem, 1000);
+        of_flow_stats_entry_cookie_set(elem, 81985529216486895);
+        of_flow_stats_entry_duration_nsec_set(elem, 2);
+        of_flow_stats_entry_duration_sec_set(elem, 1);
+        of_flow_stats_entry_hard_timeout_set(elem, 10);
+        of_flow_stats_entry_idle_timeout_set(elem, 5);
+        of_flow_stats_entry_packet_count_set(elem, 10);
+        of_flow_stats_entry_priority_set(elem, 100);
+        of_flow_stats_entry_table_id_set(elem, 3);
+        {
+            of_match_t match = { OF_VERSION_1_0 };
+            of_flow_stats_entry_match_set(elem, &match);
+        }
+        {
+            of_object_t *actions = of_list_action_new(OF_VERSION_1_0);
+            {
+                of_object_t *elem = of_action_output_new(OF_VERSION_1_0);
+                of_action_output_max_len_set(elem, 0);
+                of_action_output_port_set(elem, 1);
+                of_list_append(actions, elem);
+                of_object_delete(elem);
+            }
+            {
+                of_object_t *elem = of_action_output_new(OF_VERSION_1_0);
+                of_action_output_max_len_set(elem, 0);
+                of_action_output_port_set(elem, 2);
+                of_list_append(actions, elem);
+                of_object_delete(elem);
+            }
+            of_flow_stats_entry_actions_set(elem, actions);
+            of_object_delete(actions);
+        }
+        of_list_append(entries, elem);
+        of_object_delete(elem);
+    }
+    {
+        of_object_t *elem = of_flow_stats_entry_new(OF_VERSION_1_0);
+        of_flow_stats_entry_byte_count_set(elem, 1000);
+        of_flow_stats_entry_cookie_set(elem, 81985529216486895);
+        of_flow_stats_entry_duration_nsec_set(elem, 2);
+        of_flow_stats_entry_duration_sec_set(elem, 1);
+        of_flow_stats_entry_hard_timeout_set(elem, 10);
+        of_flow_stats_entry_idle_timeout_set(elem, 5);
+        of_flow_stats_entry_packet_count_set(elem, 10);
+        of_flow_stats_entry_priority_set(elem, 100);
+        of_flow_stats_entry_table_id_set(elem, 4);
+        {
+            of_match_t match = { OF_VERSION_1_0 };
+            of_flow_stats_entry_match_set(elem, &match);
+        }
+        {
+            of_object_t *actions = of_list_action_new(OF_VERSION_1_0);
+            {
+                of_object_t *elem = of_action_output_new(OF_VERSION_1_0);
+                of_action_output_max_len_set(elem, 0);
+                of_action_output_port_set(elem, 1);
+                of_list_append(actions, elem);
+                of_object_delete(elem);
+            }
+            {
+                of_object_t *elem = of_action_output_new(OF_VERSION_1_0);
+                of_action_output_max_len_set(elem, 0);
+                of_action_output_port_set(elem, 2);
+                of_list_append(actions, elem);
+                of_object_delete(elem);
+            }
+            {
+                of_object_t *elem = of_action_output_new(OF_VERSION_1_0);
+                of_action_output_max_len_set(elem, 0);
+                of_action_output_port_set(elem, 3);
+                of_list_append(actions, elem);
+                of_object_delete(elem);
+            }
+            of_flow_stats_entry_actions_set(elem, actions);
+            of_object_delete(actions);
+        }
+        of_list_append(entries, elem);
+        of_object_delete(elem);
+    }
+    of_flow_stats_reply_entries_set(obj, entries);
+    of_object_delete(entries);
+}
diff --git a/test_data/of10/hello.data b/test_data/of10/hello.data
index 2603365..d29dff9 100644
--- a/test_data/of10/hello.data
+++ b/test_data/of10/hello.data
@@ -4,3 +4,8 @@
 12 34 56 78 # xid
 -- python
 ofp.message.hello(xid=0x12345678)
+-- c
+obj = of_hello_new(OF_VERSION_1_0);
+of_hello_xid_set(obj, 305419896);
+-- java
+builder.setXid(0x12345678)
diff --git a/test_data/of10/packet_in.data b/test_data/of10/packet_in.data
index f8d026b..2cd98b0 100644
--- a/test_data/of10/packet_in.data
+++ b/test_data/of10/packet_in.data
@@ -16,3 +16,22 @@
     in_port=ofp.OFPP_LOCAL,
     reason=ofp.OFPR_ACTION,
     data='abc')
+-- c
+obj = of_packet_in_new(OF_VERSION_1_0);
+of_packet_in_buffer_id_set(obj, 2882400001);
+{
+    of_octets_t data = { .bytes=3, .data=(uint8_t *)"\x61\x62\x63" };
+    of_packet_in_data_set(obj, &data);
+}
+of_packet_in_in_port_set(obj, 65534);
+of_packet_in_reason_set(obj, 1);
+of_packet_in_total_len_set(obj, 9);
+of_packet_in_xid_set(obj, 305419896);
+-- java
+builder
+   .setXid(0x12345678)
+   .setBufferId(0xabcdef01)
+   .setTotalLen(9)
+   .setInPort(OFPort.LOCAL)
+   .setReason(OFPacketInReason.ACTION)
+   .setData(new byte[] { 0x61, 0x62, 0x63 } );
diff --git a/test_data/of10/packet_out.data b/test_data/of10/packet_out.data
index a3892f6..fdd1c3d 100644
--- a/test_data/of10/packet_out.data
+++ b/test_data/of10/packet_out.data
@@ -23,3 +23,31 @@
         ofp.action.output(port=1),
         ofp.action.output(port=2)],
     data='abc')
+-- c
+obj = of_packet_out_new(OF_VERSION_1_0);
+of_packet_out_buffer_id_set(obj, 2882400001);
+of_packet_out_in_port_set(obj, 65534);
+of_packet_out_xid_set(obj, 305419896);
+{
+    of_object_t *list = of_list_action_new(OF_VERSION_1_0);
+    {
+        of_object_t *obj = of_action_output_new(OF_VERSION_1_0);
+        of_action_output_max_len_set(obj, 0);
+        of_action_output_port_set(obj, 1);
+        of_list_append(list, obj);
+        of_object_delete(obj);
+    }
+    {
+        of_object_t *obj = of_action_output_new(OF_VERSION_1_0);
+        of_action_output_max_len_set(obj, 0);
+        of_action_output_port_set(obj, 2);
+        of_list_append(list, obj);
+        of_object_delete(obj);
+    }
+    of_packet_out_actions_set(obj, list);
+    of_object_delete(list);
+}
+{
+    of_octets_t data = { .bytes=3, .data=(uint8_t *)"\x61\x62\x63" };
+    of_packet_out_data_set(obj, &data);
+}
diff --git a/test_data/of10/port_desc.data b/test_data/of10/port_desc.data
index c3c2e38..56242cc 100644
--- a/test_data/of10/port_desc.data
+++ b/test_data/of10/port_desc.data
@@ -19,3 +19,20 @@
     advertised=ofp.OFPPF_1GB_FD,
     supported=ofp.OFPPF_AUTONEG,
     peer=ofp.OFPPF_PAUSE_ASYM)
+-- c
+obj = of_port_desc_new(OF_VERSION_1_0);
+of_port_desc_advertised_set(obj, 32);
+of_port_desc_config_set(obj, 16);
+of_port_desc_curr_set(obj, 1);
+{
+    of_mac_addr_t hw_addr = { { 1, 2, 3, 4, 5, 6 } };
+    of_port_desc_hw_addr_set(obj, hw_addr);
+}
+{
+    of_port_name_t name = "foo";
+    of_port_desc_name_set(obj, name);
+}
+of_port_desc_peer_set(obj, 2048);
+of_port_desc_port_no_set(obj, 65533);
+of_port_desc_state_set(obj, 512);
+of_port_desc_supported_set(obj, 512);
diff --git a/test_data/of10/port_mod.data b/test_data/of10/port_mod.data
index 972a4e8..53e09ce 100644
--- a/test_data/of10/port_mod.data
+++ b/test_data/of10/port_mod.data
@@ -16,3 +16,14 @@
     config=0x90ABCDEF,
     mask=0xFF11FF11,
     advertise=0xCAFE6789)
+-- c
+obj = of_port_mod_new(OF_VERSION_1_0);
+of_port_mod_advertise_set(obj, 3405670281);
+of_port_mod_config_set(obj, 2427178479);
+{
+    of_mac_addr_t hw_addr = { { 1, 2, 3, 4, 5, 6 } };
+    of_port_mod_hw_addr_set(obj, hw_addr);
+}
+of_port_mod_mask_set(obj, 4279369489);
+of_port_mod_port_no_set(obj, 65533);
+of_port_mod_xid_set(obj, 2);
diff --git a/test_data/of10/port_stats_reply.data b/test_data/of10/port_stats_reply.data
index 45a3532..4378387 100644
--- a/test_data/of10/port_stats_reply.data
+++ b/test_data/of10/port_stats_reply.data
@@ -37,3 +37,47 @@
     xid=5, flags=0, entries=[
         ofp.port_stats_entry(port_no=1, rx_packets=56, collisions=5),
         ofp.port_stats_entry(port_no=ofp.OFPP_LOCAL, rx_packets=1, collisions=1)])
+-- c
+obj = of_port_stats_reply_new(OF_VERSION_1_0);
+{
+    of_object_t list;
+    of_port_stats_reply_entries_bind(obj, &list);
+    {
+        of_object_t *obj = of_port_stats_entry_new(OF_VERSION_1_0);
+        of_port_stats_entry_collisions_set(obj, 5);
+        of_port_stats_entry_port_no_set(obj, 1);
+        of_port_stats_entry_rx_bytes_set(obj, 0);
+        of_port_stats_entry_rx_crc_err_set(obj, 0);
+        of_port_stats_entry_rx_dropped_set(obj, 0);
+        of_port_stats_entry_rx_errors_set(obj, 0);
+        of_port_stats_entry_rx_frame_err_set(obj, 0);
+        of_port_stats_entry_rx_over_err_set(obj, 0);
+        of_port_stats_entry_rx_packets_set(obj, 56);
+        of_port_stats_entry_tx_bytes_set(obj, 0);
+        of_port_stats_entry_tx_dropped_set(obj, 0);
+        of_port_stats_entry_tx_errors_set(obj, 0);
+        of_port_stats_entry_tx_packets_set(obj, 0);
+        of_list_append(&list, obj);
+        of_object_delete(obj);
+    }
+    {
+        of_object_t *obj = of_port_stats_entry_new(OF_VERSION_1_0);
+        of_port_stats_entry_collisions_set(obj, 1);
+        of_port_stats_entry_port_no_set(obj, 65534);
+        of_port_stats_entry_rx_bytes_set(obj, 0);
+        of_port_stats_entry_rx_crc_err_set(obj, 0);
+        of_port_stats_entry_rx_dropped_set(obj, 0);
+        of_port_stats_entry_rx_errors_set(obj, 0);
+        of_port_stats_entry_rx_frame_err_set(obj, 0);
+        of_port_stats_entry_rx_over_err_set(obj, 0);
+        of_port_stats_entry_rx_packets_set(obj, 1);
+        of_port_stats_entry_tx_bytes_set(obj, 0);
+        of_port_stats_entry_tx_dropped_set(obj, 0);
+        of_port_stats_entry_tx_errors_set(obj, 0);
+        of_port_stats_entry_tx_packets_set(obj, 0);
+        of_list_append(&list, obj);
+        of_object_delete(obj);
+    }
+}
+of_port_stats_reply_flags_set(obj, 0);
+of_port_stats_reply_xid_set(obj, 5);
diff --git a/test_data/of10/port_status.data b/test_data/of10/port_status.data
index 04da9fd..7589eae 100644
--- a/test_data/of10/port_status.data
+++ b/test_data/of10/port_status.data
@@ -28,3 +28,27 @@
         advertised=ofp.OFPPF_1GB_FD,
         supported=ofp.OFPPF_AUTONEG,
         peer=ofp.OFPPF_PAUSE_ASYM))
+-- c
+obj = of_port_status_new(OF_VERSION_1_0);
+{
+    of_object_t *desc = of_port_desc_new(OF_VERSION_1_0);
+    of_port_desc_advertised_set(desc, 32);
+    of_port_desc_config_set(desc, 16);
+    of_port_desc_curr_set(desc, 1);
+    {
+	of_mac_addr_t hw_addr = { { 1, 2, 3, 4, 5, 6 } };
+	of_port_desc_hw_addr_set(desc, hw_addr);
+    }
+    {
+	of_port_name_t name = "foo";
+	of_port_desc_name_set(desc, name);
+    }
+    of_port_desc_peer_set(desc, 2048);
+    of_port_desc_port_no_set(desc, 65533);
+    of_port_desc_state_set(desc, 512);
+    of_port_desc_supported_set(desc, 512);
+    of_port_status_desc_set(obj, desc);
+    of_object_delete(desc);
+}
+of_port_status_reason_set(obj, 1);
+of_port_status_xid_set(obj, 4);
diff --git a/test_data/of10/queue_get_config_reply.data b/test_data/of10/queue_get_config_reply.data
index 5e3453d..1016cad 100644
--- a/test_data/of10/queue_get_config_reply.data
+++ b/test_data/of10/queue_get_config_reply.data
@@ -35,3 +35,49 @@
         ofp.packet_queue(queue_id=2, properties=[
             ofp.queue_prop_min_rate(rate=6),
             ofp.queue_prop_min_rate(rate=7)])])
+-- c
+obj = of_queue_get_config_reply_new(OF_VERSION_1_0);
+of_queue_get_config_reply_port_set(obj, 65534);
+{
+    of_object_t list;
+    of_queue_get_config_reply_queues_bind(obj, &list);
+    {
+        of_object_t *obj = of_packet_queue_new(OF_VERSION_1_0);
+        {
+            of_object_t list;
+            of_packet_queue_properties_bind(obj, &list);
+            {
+                of_object_t *obj = of_queue_prop_min_rate_new(OF_VERSION_1_0);
+                of_queue_prop_min_rate_rate_set(obj, 5);
+                of_list_append(&list, obj);
+                of_object_delete(obj);
+            }
+        }
+        of_packet_queue_queue_id_set(obj, 1);
+        of_list_append(&list, obj);
+        of_object_delete(obj);
+    }
+    {
+        of_object_t *obj = of_packet_queue_new(OF_VERSION_1_0);
+        {
+            of_object_t list;
+            of_packet_queue_properties_bind(obj, &list);
+            {
+                of_object_t *obj = of_queue_prop_min_rate_new(OF_VERSION_1_0);
+                of_queue_prop_min_rate_rate_set(obj, 6);
+                of_list_append(&list, obj);
+                of_object_delete(obj);
+            }
+            {
+                of_object_t *obj = of_queue_prop_min_rate_new(OF_VERSION_1_0);
+                of_queue_prop_min_rate_rate_set(obj, 7);
+                of_list_append(&list, obj);
+                of_object_delete(obj);
+            }
+        }
+        of_packet_queue_queue_id_set(obj, 2);
+        of_list_append(&list, obj);
+        of_object_delete(obj);
+    }
+}
+of_queue_get_config_reply_xid_set(obj, 305419896);
diff --git a/test_data/of10/table_stats_entry.data b/test_data/of10/table_stats_entry.data
index 1a99237..017e8ba 100644
--- a/test_data/of10/table_stats_entry.data
+++ b/test_data/of10/table_stats_entry.data
@@ -19,3 +19,15 @@
     active_count=2,
     lookup_count=1099511627775,
     matched_count=9300233470495232273L)
+-- c
+obj = of_table_stats_entry_new(OF_VERSION_1_0);
+of_table_stats_entry_active_count_set(obj, 2);
+of_table_stats_entry_lookup_count_set(obj, 1099511627775ULL);
+of_table_stats_entry_matched_count_set(obj, 9300233470495232273ULL);
+of_table_stats_entry_max_entries_set(obj, 5);
+{
+    of_table_name_t name = "foo";
+    of_table_stats_entry_name_set(obj, name);
+}
+of_table_stats_entry_table_id_set(obj, 3);
+of_table_stats_entry_wildcards_set(obj, 4194303);