Merge pull request #329 from rlane/of14

Merge master into of14 branch
diff --git a/c_gen/build_of_g.py b/c_gen/build_of_g.py
index 9b19af6..047b254 100755
--- a/c_gen/build_of_g.py
+++ b/c_gen/build_of_g.py
@@ -361,81 +361,6 @@
     """
     Use the type members in the IR to fill out the legacy type_maps.
     """
-
-    def split_inherited_cls(cls):
-        if cls == 'of_meter_band_stats': # HACK not a subtype of of_meter_band
-            return None, None
-        for parent in sorted(type_maps.inheritance_data.keys(), reverse=True):
-            if cls.startswith(parent):
-                return (parent, cls[len(parent)+1:])
-        return None, None
-
-    def find_experimenter(parent, cls):
-        for experimenter in sorted(of_g.experimenter_name_to_id.keys(), reverse=True):
-            prefix = parent + '_' + experimenter
-            if cls.startswith(prefix) and cls != prefix:
-                return experimenter
-        return None
-
-    def find_type_value(ofclass, m_name):
-        for m in ofclass.members:
-            if isinstance(m, OFTypeMember) and m.name == m_name:
-                return m.value
-        raise KeyError("ver=%d, cls=%s, m_name=%s" % (wire_version, cls, m_name))
-
-    # Most inheritance classes: actions, instructions, etc
-    for version, protocol in loxi_globals.ir.items():
-        wire_version = version.wire_version
-        for ofclass in protocol.classes:
-            cls = ofclass.name
-            parent, subcls = split_inherited_cls(cls)
-            if not (parent and subcls):
-                continue
-            if parent == 'of_oxm':
-                type_len = find_type_value(ofclass, 'type_len')
-                oxm_class = (type_len >> 16) & 0xffff
-                if oxm_class != 0x8000:
-                    # Do not include experimenter OXMs in the main table
-                    val = type_maps.invalid_type
-                else:
-                    val = (type_len >> 8) & 0xff
-            else:
-                val = find_type_value(ofclass, 'type')
-            type_maps.inheritance_data[parent][wire_version][subcls] = val
-
-            # Extensions (only actions for now)
-            experimenter = find_experimenter(parent, cls)
-            if parent == 'of_action' and experimenter:
-                val = find_type_value(ofclass, 'subtype')
-                type_maps.extension_action_subtype[wire_version][experimenter][cls] = val
-                if wire_version >= of_g.VERSION_1_3:
-                    cls2 = parent + "_id" + cls[len(parent):]
-                    type_maps.extension_action_id_subtype[wire_version][experimenter][cls2] = val
-            elif parent == 'of_instruction' and experimenter:
-                val = find_type_value(ofclass, 'subtype')
-                type_maps.extension_instruction_subtype[wire_version][experimenter][cls] = val
-
-    # Messages
-    for version, protocol in loxi_globals.ir.items():
-        wire_version = version.wire_version
-        for ofclass in protocol.classes:
-            cls = ofclass.name
-            # HACK (though this is what loxi_utils.class_is_message() does)
-            if not [x for x in ofclass.members if isinstance(x, OFDataMember) and x.name == 'xid']:
-                continue
-            if type_maps.class_is_virtual(cls):
-                continue
-            subcls = cls[3:]
-            val = find_type_value(ofclass, 'type')
-            if not val in type_maps.message_types[wire_version].values():
-                type_maps.message_types[wire_version][subcls] = val
-
-            # Extensions
-            experimenter = find_experimenter('of', cls)
-            if experimenter and ofclass.is_subclassof("of_experimenter"):
-                val = find_type_value(ofclass, 'subtype')
-                type_maps.extension_message_subtype[wire_version][experimenter][cls] = val
-
     type_maps.generate_maps()
 
 def analyze_input():
@@ -448,7 +373,7 @@
     for wire_version, ordered_classes in of_g.ordered_classes.items():
         classes = versions[of_g.of_version_wire2name[wire_version]]['classes']
         for cls in ordered_classes:
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 new_cls = cls + '_header'
                 of_g.ordered_classes[wire_version].append(new_cls)
                 classes[new_cls] = classes[cls]
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index 6556d3b..3229403 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -874,61 +874,6 @@
 #define OF_MESSAGE_OBJECT_COUNT %d
 """ % ((last + 1), msg_count))
 
-    # Generate object type range checking for inheritance classes
-
-    # @fixme These should be determined algorithmicly
-    out.write("""
-/*
- * Macros to check if an object ID is within an inheritance class range
- */
-""")
-    # Alphabetical order for 'last'
-    last_ids = dict(of_action="OF_ACTION_STRIP_VLAN",
-                    of_oxm="OF_OXM_VLAN_VID_MASKED",
-                    of_instruction="OF_INSTRUCTION_WRITE_METADATA",
-                    of_queue_prop="OF_QUEUE_PROP_MIN_RATE",
-                    of_table_feature_prop="OF_TABLE_FEATURE_PROP_WRITE_SETFIELD_MISS",
-                    # @FIXME add meter_band ?
-                    )
-    for cls, last in last_ids.items():
-        out.write("""
-#define %(enum)s_FIRST_ID      (%(enum)s + 1)
-#define %(enum)s_LAST_ID       %(last)s
-#define %(enum)s_VALID_ID(id) \\
-    ((id) >= %(enum)s_FIRST_ID && \\
-     (id) <= %(enum)s_LAST_ID)
-""" % dict(enum=enum_name(cls), last=last))
-    out.write("""
-/**
- * Function to check a wire ID
- * @param object_id The ID to check
- * @param base_object_id The inheritance parent, if applicable
- * @returns boolean: If base_object_id is an inheritance class, check if
- * object_id is valid as a subclass.  Otherwise return 1.
- *
- * Note: Could check that object_id == base_object_id in the
- * second case.
- */
-static inline int
-of_wire_id_valid(int object_id, int base_object_id) {
-    switch (base_object_id) {
-    case OF_ACTION:
-        return OF_ACTION_VALID_ID(object_id);
-    case OF_OXM:
-        return OF_OXM_VALID_ID(object_id);
-    case OF_QUEUE_PROP:
-        return OF_QUEUE_PROP_VALID_ID(object_id);
-    case OF_TABLE_FEATURE_PROP:
-        return OF_TABLE_FEATURE_PROP_VALID_ID(object_id);
-    case OF_INSTRUCTION:
-        return OF_INSTRUCTION_VALID_ID(object_id);
-    default:
-        break;
-    }
-    return 1;
-}
-""")
-
 ################################################################
 #
 # Internal Utility Functions
@@ -1055,7 +1000,8 @@
     %(cls)s_header_t header; /* Generic instance */
 """ % dict(cls=cls))
         for subcls in sorted(subclasses):
-            out.write("    %s_%s_t %s;\n" % (cls, subcls, subcls))
+            instance = loxi_utils.class_to_instance(subcls, cls)
+            out.write("    %s_%s_t %s;\n" % (cls, instance, instance))
         out.write("};\n")
 
 def gen_struct_typedefs(out):
@@ -1069,7 +1015,7 @@
         out.write("typedef union %(cls)s_u %(cls)s_t;\n" % dict(cls=cls))
     out.write("\n/* LOCI object typedefs */\n")
     for cls in of_g.standard_class_order:
-        if cls in type_maps.inheritance_map:
+        if type_maps.class_is_inheritance_root(cls):
             continue
         template = "typedef of_object_t %(cls)s_t;\n"
         out.write(template % dict(cls=cls))
@@ -1109,7 +1055,7 @@
  ****************************************************************/
 """)
     for cls in of_g.standard_class_order:
-        if cls in type_maps.inheritance_map:
+        if type_maps.class_is_inheritance_root(cls):
             continue
         out.write("\n/* Unified accessor functions for %s */\n" % cls)
         for m_name in of_g.ordered_members[cls]:
@@ -1629,7 +1575,7 @@
     @param cls The class name for the function
     @param out The file to which to write
     """
-    if cls in type_maps.inheritance_map:
+    if type_maps.class_is_inheritance_root(cls):
         param = "obj_p"
     else:
         param = "obj"
@@ -1659,7 +1605,7 @@
 """ % dict(cls=cls, param=param))
 
     # Use an extra pointer to deal with inheritance classes
-    if cls in type_maps.inheritance_map:
+    if type_maps.class_is_inheritance_root(cls):
         out.write("""\
     %s_header_t *obj;
 
@@ -1862,7 +1808,7 @@
  ****************************************************************/
 """)
     for cls in of_g.standard_class_order:
-#        if cls in type_maps.inheritance_map:
+#        if type_maps.class_is_inheritance_root(cls):
 #            continue
         out.write("""
 /**
@@ -1921,7 +1867,7 @@
     out.write("/* DOCUMENTATION ONLY */\n")
 
     for cls in of_g.standard_class_order:
-        if cls in type_maps.inheritance_map:
+        if type_maps.class_is_inheritance_root(cls):
             pass # Check this
 
         out.write("""
diff --git a/c_gen/c_dump_gen.py b/c_gen/c_dump_gen.py
index d4a016c..2f41c35 100644
--- a/c_gen/c_dump_gen.py
+++ b/c_gen/c_dump_gen.py
@@ -90,7 +90,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             out.write("""\
 int %(cls)s_%(ver_name)s_dump(loci_writer_f writer, void* cookie, %(cls)s_t *obj);
@@ -129,7 +129,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             out.write("""
 int
@@ -234,7 +234,7 @@
                 comma = ","
 
             if (not loxi_utils.class_in_version(cls, version) or
-                    cls in type_maps.inheritance_map):
+                    type_maps.class_is_inheritance_root(cls)):
                 out.write("    unknown_dump%s\n" % comma);
             else:
                 out.write("    %s_%s_dump%s\n" %
diff --git a/c_gen/c_show_gen.py b/c_gen/c_show_gen.py
index 9d84477..f4d7945 100644
--- a/c_gen/c_show_gen.py
+++ b/c_gen/c_show_gen.py
@@ -43,6 +43,78 @@
 import c_gen.identifiers as identifiers
 from c_test_gen import var_name_map
 
+show_override = {
+    ('uint32_t', 'arp_tpa'): 'ipv4',
+    ('uint32_t', 'arp_spa'): 'ipv4',
+    ('uint32_t', 'nw_addr'): 'ipv4',
+    ('uint32_t', 'dst'): 'ipv4',
+}
+
+show_hex = set([
+    ('uint8_t', 'icmpv6_code'),
+    ('uint8_t', 'mpls_tc'),
+    ('uint16_t', 'eth_type'),
+    ('uint8_t', 'ip_dscp'),
+    ('uint64_t', 'metadata'),
+    ('uint16_t', 'ingress_tpid'),
+    ('uint16_t', 'egress_tpid'),
+    ('uint32_t', 'xid'),
+    ('uint16_t', 'flags'),
+    ('uint32_t', 'experimenter'),
+    ('uint32_t', 'mask'),
+    ('uint8_t', 'report_mirror_ports'),
+    ('uint64_t', 'datapath_id'),
+    ('uint32_t', 'capabilities'),
+    ('uint32_t', 'actions'),
+    ('uint64_t', 'cookie'),
+    ('uint8_t', 'reason'),
+    ('uint32_t', 'role'),
+    ('uint32_t', 'config'),
+    ('uint32_t', 'advertise'),
+    ('uint32_t', 'advertised'),
+    ('uint32_t', 'supported'),
+    ('uint32_t', 'peer'),
+    ('uint64_t', 'cookie_mask'),
+    ('uint32_t', 'reserved'),
+    ('uint16_t', 'ethertype'),
+    ('uint64_t', 'metadata_mask'),
+    ('uint32_t', 'instructions'),
+    ('uint32_t', 'write_actions'),
+    ('uint32_t', 'apply_actions'),
+    ('uint32_t', 'types'),
+    ('uint32_t', 'actions_all'),
+    ('uint32_t', 'actions_select'),
+    ('uint32_t', 'actions_indirect'),
+    ('uint32_t', 'actions_ff'),
+    ('uint64_t', 'generation_id'),
+    ('uint16_t', 'value_mask'),
+    ('uint32_t', 'value_mask'),
+    ('uint32_t', 'oxm_header'),
+    ('uint8_t', 'value_mask'),
+    ('uint64_t', 'value_mask'),
+    ('uint64_t', 'write_setfields'),
+    ('uint64_t', 'apply_setfields'),
+    ('uint64_t', 'metadata_match'),
+    ('uint64_t', 'metadata_write'),
+    ('uint32_t', 'packet_in_mask_equal_master'),
+    ('uint32_t', 'packet_in_mask_slave'),
+    ('uint32_t', 'port_status_mask_equal_master'),
+    ('uint32_t', 'port_status_mask_slave'),
+    ('uint32_t', 'flow_removed_mask_equal_master'),
+    ('uint32_t', 'flow_removed_mask_slave'),
+    ('uint32_t', 'band_types'),
+    ('uint16_t', 'bsn_tcp_flags'),
+])
+
+def gen_emitter(cls, m_name, m_type):
+    if (m_type, m_name) in show_override:
+        short_type = show_override[(m_type, m_name)]
+    elif (m_type, m_name) in show_hex:
+        short_type = loxi_utils.type_to_short_name(m_type).replace('u', 'x')
+    else:
+        short_type = loxi_utils.type_to_short_name(m_type)
+    return "LOCI_SHOW_" + short_type;
+
 def gen_obj_show_h(out, name):
     loxi_utils.gen_c_copy_license(out)
     out.write("""
@@ -91,7 +163,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             out.write("""\
 int %(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, %(cls)s_t *obj);
@@ -130,7 +202,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             out.write("""
 int
@@ -155,8 +227,7 @@
             for member in members:
                 m_type = member["m_type"]
                 m_name = member["name"]
-                #emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type)
-                emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) + "_" + m_name;
+                emitter = gen_emitter(cls, m_name, m_type)
                 if loxi_utils.skip_member_name(m_name):
                     continue
                 if (loxi_utils.type_is_scalar(m_type) or
@@ -204,8 +275,7 @@
 
     for key, entry in match.of_match_members.items():
         m_type = entry["m_type"]
-        #emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type)
-        emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) + "_" + key;
+        emitter = gen_emitter('of_match', key, m_type)
         out.write("""
     if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(match)) {
         out += writer(cookie, "%(key)s active=");
@@ -233,7 +303,7 @@
                 comma = ","
 
             if (not loxi_utils.class_in_version(cls, version) or
-                    cls in type_maps.inheritance_map):
+                    type_maps.class_is_inheritance_root(cls)):
                 out.write("    unknown_show%s\n" % comma);
             else:
                 out.write("    %s_%s_show%s\n" %
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index 71615e6..41fe122 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -124,6 +124,13 @@
 scalar_types = integer_types[:]
 scalar_types.extend(string_types)
 
+# When embedding an object inside of another object we have to pick a single
+# subclass to use, unlike lists where we use all subclasses.
+embedded_subclasses = {
+    'of_oxm_header_t': 'of_oxm_eth_type',
+    'of_bsn_vport_header_t': 'of_bsn_vport_q_in_q',
+}
+
 def ignore_member(cls, version, m_name, m_type):
     """
     Filter out names or types that either don't have accessors
@@ -372,7 +379,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             out.write("""
 extern int %(cls)s_%(v_name)s_populate(
@@ -507,7 +514,7 @@
  */
 """ % v_name)
         for cls in of_g.standard_class_order:
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             if version in of_g.unified[cls]:
                 message_scalar_test(out, version, cls)
@@ -520,7 +527,7 @@
     for version in of_g.of_version_range:
         v_name = loxi_utils.version_to_name(version)
         for cls in of_g.standard_class_order:
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             if version in of_g.unified[cls]:
                 test_name = "%s_%s" % (cls, v_name)
@@ -1301,8 +1308,9 @@
     for m_type in member_types:
         if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
             out.write("    %s %s;\n" % (m_type, var_name_map(m_type)))
-        elif m_type == "of_bsn_vport_header_t":
-            out.write("    of_bsn_vport_q_in_q_t *%s;\n" % var_name_map(m_type))
+        elif m_type in embedded_subclasses:
+            subcls = embedded_subclasses[m_type]
+            out.write("    %s_t *%s;\n" % (subcls, var_name_map(m_type)))
         else:
             out.write("    %s *%s;\n" % (m_type, var_name_map(m_type)))
     out.write("""
@@ -1313,7 +1321,7 @@
         m_name = member["name"]
         if loxi_utils.skip_member_name(m_name):
             continue
-        if m_type == "of_bsn_vport_header_t":
+        if m_type in embedded_subclasses:
             continue
         if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
             out.write("""\
@@ -1363,8 +1371,8 @@
         FREE(octets.data);
     }
 """ % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
-        elif m_type == "of_bsn_vport_header_t": # test q_in_q
-            sub_cls = "of_bsn_vport_q_in_q"
+        elif m_type in embedded_subclasses:
+            sub_cls = embedded_subclasses[m_type]
             out.write("""\
     %(var_name)s = %(sub_cls)s_new(%(v_name)s);
     TEST_ASSERT(%(var_name)s != NULL);
@@ -1443,8 +1451,8 @@
     value = of_octets_check(&%(var_name)s, value);
 """ % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
            v_name=loxi_utils.version_to_name(version)))
-        elif m_type == "of_bsn_vport_header_t": # tests only q_in_q
-            sub_cls = "of_bsn_vport_q_in_q"
+        elif m_type in embedded_subclasses:
+            sub_cls = embedded_subclasses[m_type]
             out.write("""
     { /* Use get/delete to access on check */
         %(sub_cls)s_t *%(m_name)s_ptr;
@@ -1565,7 +1573,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             elif loxi_utils.class_is_list(cls):
                 gen_list_setup_check(out, cls, version)
@@ -1588,7 +1596,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             unified_accessor_test_case(out, cls, version)
 
@@ -1602,7 +1610,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             test_name = "%s_%s" % (cls, v_name)
             out.write("    RUN_TEST(%s);\n" % test_name)
@@ -1682,13 +1690,13 @@
 """ % dict(cls=cls, ver_name=ver_name))
 
     # For each subclass, check if this is an instance of that subclass
-    version_classes = type_maps.inheritance_data[cls][version]
-    for sub_cls in version_classes:
-        sub_enum = (cls + "_" + sub_cls).upper()
+    sub_classes = type_maps.sub_class_map(cls, version)
+    for (_, sub_cls) in sub_classes:
+        sub_enum = sub_cls.upper()
         out.write("""
     if (src->header.object_id == %(sub_enum)s) {
-        return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
-            &src->%(sub_cls)s);
+        return (%(cls)s_t *)%(sub_cls)s_%(ver_name)s_dup(
+            (of_object_t *)src);
     }
 """ % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
 
@@ -1728,11 +1736,12 @@
         if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
             # Declare instance of these
             out.write("    %s %s;\n" % (m_type, var_name_map(m_type)))
-        elif m_type == "of_bsn_vport_header_t": # test q_in_q
+        elif m_type in embedded_subclasses:
+            sub_cls = embedded_subclasses[m_type]
             out.write("""
-    of_bsn_vport_q_in_q_t src_%(v_name)s;
-    of_bsn_vport_q_in_q_t *dst_%(v_name)s;
-""" % dict(v_name=var_name_map(m_type)))
+    %(sub_cls)s_t src_%(v_name)s;
+    %(sub_cls)s_t *dst_%(v_name)s;
+""" % dict(v_name=var_name_map(m_type), sub_cls=sub_cls))
         else:
             out.write("""
     %(m_type)s src_%(v_name)s;
@@ -1760,8 +1769,8 @@
     %(cls)s_%(m_name)s_get(src, &%(v_name)s);
     %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
 """ % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
-        elif m_type == "of_bsn_vport_header_t": # test q_in_q
-            sub_cls = "of_bsn_vport_q_in_q"
+        elif m_type in embedded_subclasses:
+            sub_cls = embedded_subclasses[m_type]
             out.write("""
     %(cls)s_%(m_name)s_bind(
         src, &src_%(v_name)s);
@@ -1814,7 +1823,7 @@
         for cls in of_g.standard_class_order:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 gen_dup_inheritance(out, cls, version)
             elif loxi_utils.class_is_list(cls):
                 gen_dup_list(out, cls, version)
@@ -1836,7 +1845,7 @@
         for version in of_g.of_version_range:
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            hdr = "header." if cls in type_maps.inheritance_map else ""
+            hdr = "header." if type_maps.class_is_inheritance_root(cls) else ""
 
             ver_name = loxi_utils.version_to_name(version)
             out.write("""
@@ -1940,7 +1949,7 @@
         for j, cls in enumerate(of_g.all_class_order):
             if not loxi_utils.class_in_version(cls, version):
                 continue
-            if cls in type_maps.inheritance_map:
+            if type_maps.class_is_inheritance_root(cls):
                 continue
             if cls == "of_bsn_virtual_port_create_request": # test q_in_q
                 out.write("""
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index 07b0ade..c1b00ad 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -207,69 +207,29 @@
         if uclass and not uclass.virtual and uclass.has_type_members:
             wire_type_set = '%s_push_wire_types' % uclass.name
 
+        root = uclass.inheritance_root()
+        if root and root.name != 'of_header':
+            wire_type_get = root.name + '_wire_object_id_get'
+
         if uclass.is_message:
             wire_length_get = 'of_object_message_wire_length_get'
             wire_length_set = 'of_object_message_wire_length_set'
-        elif uclass.is_action:
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_action_wire_object_id_get'
-        elif uclass.is_instanceof('of_bsn_vport'):
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_bsn_vport_wire_object_id_get'
-        elif uclass.is_action_id:
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_action_id_wire_object_id_get'
-        elif uclass.is_instruction:
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_instruction_wire_object_id_get'
-        elif uclass.is_instanceof('of_instruction_id'):
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_instruction_id_wire_object_id_get'
-        elif uclass.is_instanceof('of_queue_prop'):
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_queue_prop_wire_object_id_get'
-        elif uclass.is_instanceof('of_table_feature_prop'):
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_table_feature_prop_wire_object_id_get'
-        elif uclass.is_instanceof('of_meter_band'):
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_meter_band_wire_object_id_get'
-        elif uclass.is_instanceof('of_hello_elem'):
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_hello_elem_wire_object_id_get'
-        elif uclass.is_instanceof('of_bsn_tlv'):
-            wire_length_set = 'of_tlv16_wire_length_set'
-            wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_get = 'of_bsn_tlv_wire_object_id_get'
         elif uclass.is_oxm:
             wire_length_get = 'of_oxm_wire_length_get'
-            wire_type_get = 'of_oxm_wire_object_id_get'
         elif uclass.name == "of_packet_queue":
+            # u16 len, but at offset 4
             wire_length_get = 'of_packet_queue_wire_length_get'
             wire_length_set = 'of_packet_queue_wire_length_set'
         elif uclass.name == "of_meter_stats":
+            # u16 len, but at offset 4
             wire_length_get = 'of_meter_stats_wire_length_get'
             wire_length_set = 'of_meter_stats_wire_length_set'
-        elif uclass.name in ["of_group_desc_stats_entry", "of_group_stats_entry",
-                "of_flow_stats_entry", "of_bucket", "of_table_features",
-                "of_bsn_port_counter_stats_entry", "of_bsn_vlan_counter_stats_entry",
-                "of_bsn_gentable_entry_desc_stats_entry", "of_bsn_gentable_entry_stats_entry",
-                "of_bsn_gentable_desc_stats_entry", "of_bsn_vrf_counter_stats_entry"]:
-            wire_length_get = "of_u16_len_wire_length_get"
-            wire_length_set = "of_u16_len_wire_length_set"
-        elif uclass.name == 'of_match_v3':
+        elif loxi_utils_legacy.class_is_tlv16(uclass.name):
             wire_length_set = 'of_tlv16_wire_length_set'
             wire_length_get = 'of_tlv16_wire_length_get'
-            wire_type_set = 'of_match_v3_push_wire_types'
+        elif loxi_utils_legacy.class_is_u16_len(uclass.name):
+            wire_length_get = "of_u16_len_wire_length_get"
+            wire_length_set = "of_u16_len_wire_length_set"
 
         class_metadata.append(ClassMetadata(
             name=uclass.name,
@@ -278,74 +238,15 @@
             wire_type_get=wire_type_get,
             wire_type_set=wire_type_set))
 
-    class_metadata.extend([
-        ClassMetadata(
-            name="of_action_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_action_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_action_id_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_action_id_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_bsn_vport_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_bsn_vport_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_instruction_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_instruction_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_instruction_id_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_instruction_id_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_queue_prop_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_queue_prop_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_table_feature_prop_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_table_feature_prop_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_meter_band_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_meter_band_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_hello_elem_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_hello_elem_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_bsn_tlv_header",
-            wire_length_set='of_tlv16_wire_length_set',
-            wire_length_get='of_tlv16_wire_length_get',
-            wire_type_get='of_bsn_tlv_wire_object_id_get',
-            wire_type_set='NULL'),
-        ClassMetadata(
-            name="of_oxm_header",
-            wire_length_set='NULL',
-            wire_length_get='of_oxm_wire_length_get',
-            wire_type_get='of_oxm_wire_object_id_get',
-            wire_type_set='NULL'),
-    ])
+        # If this is the root of an inheritance hierachy, add metadata
+        # for the corresponding header class
+        if uclass.name in type_maps.inheritance_map:
+            class_metadata.append(ClassMetadata(
+                name=uclass.name + '_header',
+                wire_length_get=wire_length_get,
+                wire_length_set=wire_length_set,
+                wire_type_get=wire_type_get,
+                wire_type_set=wire_type_set))
 
     for metadata in class_metadata:
         class_metadata_dict[metadata.name] = metadata
diff --git a/c_gen/loxi_utils_legacy.py b/c_gen/loxi_utils_legacy.py
index 4472ffa..0399638 100644
--- a/c_gen/loxi_utils_legacy.py
+++ b/c_gen/loxi_utils_legacy.py
@@ -37,6 +37,8 @@
 import c_gen.of_g_legacy as of_g
 import tenjin
 from generic_utils import find, memoize
+import loxi_globals
+from loxi_ir import ir
 
 def class_signature(members):
     """
@@ -99,40 +101,49 @@
     """
     Return True if cls_name is an object which uses uint16 for type and length
     """
-    if cls.find("of_action") == 0: # Includes of_action_id classes
-        return True
-    if cls.find("of_instruction") == 0:
-        return True
-    if cls.find("of_queue_prop") == 0:
-        return True
-    if cls.find("of_table_feature_prop") == 0:
-        return True
-    # *sigh*
-    if cls.find("of_meter_band_stats") == 0:  # NOT A TLV
+
+    ofclass = loxi_globals.unified.class_by_name(cls)
+    if not ofclass:
         return False
-    if cls.find("of_meter_band") == 0:
-        return True
-    if cls.find("of_hello_elem") == 0:
-        return True
-    if cls == "of_match_v3":
-        return True
-    if cls == "of_match_v4":
-        return True
-    if cls.find("of_bsn_tlv") == 0:
-        return True
-    if cls.find("of_bsn_vport") == 0:
-        return True
-    return False
+
+    if len(ofclass.members) < 2:
+        return False
+
+    m1 = ofclass.members[0]
+    m2 = ofclass.members[1]
+
+    if not (isinstance(m1, ir.OFTypeMember) or isinstance(m1, ir.OFDiscriminatorMember)):
+        return False
+
+    if not isinstance(m2, ir.OFLengthMember):
+        return False
+
+    if m1.oftype != "uint16_t" or m2.oftype != "uint16_t":
+        return False
+
+    return True
 
 def class_is_u16_len(cls):
     """
     Return True if cls_name is an object which uses initial uint16 length
     """
-    return cls in ["of_group_desc_stats_entry", "of_group_stats_entry",
-                   "of_flow_stats_entry", "of_bucket", "of_table_features",
-                   "of_bsn_port_counter_stats_entry", "of_bsn_vlan_counter_stats_entry",
-                   "of_bsn_gentable_entry_desc_stats_entry", "of_bsn_gentable_entry_stats_entry",
-                   "of_bsn_gentable_desc_stats_entry", "of_bsn_vrf_counter_stats_entry"]
+
+    ofclass = loxi_globals.unified.class_by_name(cls)
+    if not ofclass:
+        return False
+
+    if len(ofclass.members) < 1:
+        return False
+
+    m = ofclass.members[0]
+
+    if not isinstance(m, ir.OFLengthMember):
+        return False
+
+    if m.oftype != "uint16_t":
+        return False
+
+    return True
 
 def class_is_list(cls):
     """
@@ -219,6 +230,10 @@
     """
     return parent + "_" + instance
 
+def class_to_instance(cls, base_cls):
+    assert cls.startswith(base_cls + '_')
+    return cls[len(base_cls)+1:]
+
 def class_is_var_len(cls, version):
     # Match is special case.  Only version 1.2 (wire version 3) is var
     if cls == "of_match":
@@ -283,7 +298,7 @@
     """
     Convert an integer version to the C macro name
     """
-    return "OF_" + of_g.version_names[version]
+    return of_g.of_version_wire2name[version]
 
 def gen_c_copy_license(out):
     """
diff --git a/c_gen/of_g_legacy.py b/c_gen/of_g_legacy.py
index b58ca08..2372b31 100644
--- a/c_gen/of_g_legacy.py
+++ b/c_gen/of_g_legacy.py
@@ -31,8 +31,7 @@
 # @fixme This needs to be refactored and brought into the 21st century.
 #
 
-import sys
-# @fixme Replace with argparse
+import loxi_globals
 
 ################################################################
 #
@@ -286,25 +285,21 @@
 # Indexed by (cls, version, member-name) and value is prev-member-name
 special_offsets = {}
 
-## Define Python variables with integer wire version values
-VERSION_1_0 = 1
-VERSION_1_1 = 2
-VERSION_1_2 = 3
-VERSION_1_3 = 4
-
-version_names = {1:"VERSION_1_0", 2:"VERSION_1_1", 3:"VERSION_1_2",
-                 4:"VERSION_1_3"}
-short_version_names = {1:"OF_1_0", 2:"OF_1_1", 3:"OF_1_2", 4:"OF_1_3"}
+# Map from wire version to OF_1_x
+short_version_names = {}
 
 # The iteration object that gives the wire versions supported
-of_version_range = [VERSION_1_0, VERSION_1_1, VERSION_1_2, VERSION_1_3]
+of_version_range = []
 
-of_version_wire2name = {
-    VERSION_1_0:"OF_VERSION_1_0",
-    VERSION_1_1:"OF_VERSION_1_1",
-    VERSION_1_2:"OF_VERSION_1_2",
-    VERSION_1_3:"OF_VERSION_1_3"
-    }
+# Map from wire version to OF_VERSION_1_x
+of_version_wire2name = {}
+
+for version in loxi_globals.OFVersions.all_supported:
+    v = version.version.replace('.', '_')
+    short_version_names[version.wire_version] = 'OF_' + v
+    of_version_range.append(version.wire_version)
+    of_version_wire2name[version.wire_version] = 'OF_VERSION_' + v
+    globals()['VERSION_' + v] = version.wire_version
 
 
 ################################################################
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index 239bf57..a227645 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -67,61 +67,6 @@
 #define LOCI_SHOW_d32(writer, cookie, val) LOCI_SHOW_D_INT(cookie, PRId32, val)
 #define LOCI_SHOW_d64(writer, cookie, val) LOCI_SHOW_D_INT(cookie, PRId64, val)
 
-
-
-/**
- * Field-specific show macros. 
- */
-#define LOCI_SHOW_u32_ipv6_flabel(writer, cookie, val)     LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_vlan_pcp(writer, cookie, val)         LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_src(writer, cookie, val)        LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv6_ipv6_dst(writer, cookie, val)       LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u32_arp_tpa(writer, cookie, val)         LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv6_type(writer, cookie, val)      LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_mac_arp_sha(writer, cookie, val)         LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_ipv6_ipv6_src(writer, cookie, val)       LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u16_sctp_src(writer, cookie, val)        LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv6_code(writer, cookie, val)      LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_dst(writer, cookie, val)         LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_ipv6_nd_sll(writer, cookie, val)     LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u8_mpls_tc(writer, cookie, val)          LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_u64_tunnel_id(writer, cookie, val)       LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u16_arp_op(writer, cookie, val)          LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_eth_type(writer, cookie, val)        LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_ipv6_ipv6_nd_target(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u16_vlan_vid(writer, cookie, val)        LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_arp_tha(writer, cookie, val)         LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_port_no_in_port(writer, cookie, val)     LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u8_ip_dscp(writer, cookie, val)          LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_u16_sctp_dst(writer, cookie, val)        LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv4_code(writer, cookie, val)      LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_tcp_src(writer, cookie, val)         LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_arp_spa(writer, cookie, val)         LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_ip_ecn(writer, cookie, val)           LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_udp_dst(writer, cookie, val)         LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_port_no_in_phy_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_dst(writer, cookie, val)        LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_src(writer, cookie, val)         LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u16_udp_src(writer, cookie, val)         LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_ipv6_nd_tll(writer, cookie, val)     LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv4_type(writer, cookie, val)      LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_mpls_label(writer, cookie, val)      LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_tcp_dst(writer, cookie, val)         LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_ip_proto(writer, cookie, val)         LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata(writer, cookie, val)        LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u8_enabled(writer, cookie, val)          LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_vport_no(writer, cookie, val)        LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_port_no(writer, cookie, val)         LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_ingress_tpid(writer, cookie, val)    LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u16_egress_tpid(writer, cookie, val)     LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u16_ingress_vlan_id(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_egress_vlan_id(writer, cookie, val)  LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_enabled(writer, cookie, val)         LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_enable(writer, cookie, val)          LOCI_SHOW_u32(writer, cookie, val)
-
-
-
-
 /* @todo Add checks for special port numbers */
 #define LOCI_SHOW_port_no(writer, cookie, val) writer(cookie, "%d", val)
 #define LOCI_SHOW_fm_cmd(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
@@ -173,249 +118,4 @@
  */
 int of_object_show(loci_writer_f writer, void *cookie, of_object_t *obj);
 
-
-
-
-/**
- * Choose a representation for each field that 
- * makes the most sense for display to the user. 
- */
-#define LOCI_SHOW_u32_xid(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u16_flags(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u64_packet_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_byte_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_flow_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_match_match(writer, cookie, val) LOCI_SHOW_match(writer, cookie, val)
-#define LOCI_SHOW_u8_table_id(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_port_no_out_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u32_experimenter(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_subtype(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_index(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_mask(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_report_mirror_ports(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_desc_str_mfr_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_hw_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_sw_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_ser_num_serial_num(writer, cookie, val) LOCI_SHOW_ser_num(writer, cookie, val)
-#define LOCI_SHOW_desc_str_dp_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_pipeline(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_octets_data(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_octets_value(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_u16_err_type(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_code(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u64_datapath_id(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u32_n_buffers(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_n_tables(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_capabilities(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u64_cookie(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u16_idle_timeout(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_hard_timeout(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_buffer_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_reason(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_u32_duration_sec(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_duration_nsec(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_miss_send_len(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_role(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u16_total_len(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_port_no_port_no(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_port_no_loopback_port_no(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_mac_hw_addr(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u32_config(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_advertise(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_port_no_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u32_queue_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_dest_port(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_vlan_tag(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_copy_stage(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_max_len(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_dl_addr(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u32_nw_addr(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_nw_tos(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_tp_port(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_wc_bmap_wildcards(writer, cookie, val) LOCI_SHOW_wc_bmap(writer, cookie, val)
-#define LOCI_SHOW_port_name_name(writer, cookie, val) LOCI_SHOW_port_name(writer, cookie, val)
-#define LOCI_SHOW_u32_state(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_curr(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_advertised(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_supported(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_peer(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets_unicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets_multicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets_broadcast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_uint64_value(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets_unicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets_multicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets_broadcast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_bytes(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_bytes(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_dropped(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_dropped(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_errors(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_errors(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_frame_err(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_over_err(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_crc_err(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_collisions(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u16_rate(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_tab_name_name(writer, cookie, val) LOCI_SHOW_tab_name(writer, cookie, val)
-#define LOCI_SHOW_u32_max_entries(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_active_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_lookup_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_matched_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_out_group(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_cookie_mask(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u32_reserved(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u16_command(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_group_type(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_group_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_ethertype(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u8_mpls_ttl(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_nw_ecn(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_nw_ttl(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_weight(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_port_no_watch_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u32_watch_group(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_ref_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata_mask(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_src_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_dst_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_src_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_dst_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u32_curr_speed(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_speed(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_match_bmap_match(writer, cookie, val) LOCI_SHOW_match_bmap(writer, cookie, val)
-#define LOCI_SHOW_u32_instructions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_write_actions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_apply_actions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_types(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_all(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_select(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_indirect(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_ff(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_all(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_select(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_indirect(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_ff(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u64_generation_id(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_octets_field(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_u16_value(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_value_mask(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_mac_value(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_value_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u32_value(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_value_mask(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_oxm_header(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_value(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_value_mask(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_port_no_value(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_port_no_value_mask(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_ipv6_value(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_ipv6_value_mask(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u64_value(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_value_mask(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_write_setfields(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_apply_setfields(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata_match(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata_write(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u32_packet_in_mask_equal_master(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_packet_in_mask_slave(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_port_status_mask_equal_master(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_port_status_mask_slave(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_flow_removed_mask_equal_master(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_flow_removed_mask_slave(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_auxiliary_id(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_meter_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_rate(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_burst_size(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_prec_level(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u64_packet_band_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_byte_band_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_max_meter(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_band_types(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_max_bands(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_max_color(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u64_packet_in_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_byte_in_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_octets_experimenter_data(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_u32_dst(writer, cookie, val)        LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u32_service(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_status(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_subtype(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_addr(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_netmask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_l2_table_enable(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_l2_table_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_ipv4_value(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_value_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_hybrid_enable(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_hybrid_version(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_bitmap_128_value(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
-#define LOCI_SHOW_bitmap_128_value_mask(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
-#define LOCI_SHOW_bitmap_128_bsn_in_ports_128(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
-#define LOCI_SHOW_u32_timeout_ms(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_tx_interval_ms(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_slot_num(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_lag_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_vrf(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_bsn_global_vrf_allowed(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_l3_interface_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_l3_src_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_l3_dst_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_convergence_status(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_sys_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_actor_sys_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_port_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_port_num(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_key(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_sys_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_partner_sys_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_port_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_port_num(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_key(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u64_time_ms(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_desc_str_uri(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_u8_state(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_table_id(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_deleted_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_error_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_checksum_128_checksum(writer, cookie, val) LOCI_SHOW_checksum_128(writer, cookie, val)
-#define LOCI_SHOW_checksum_128_checksum_mask(writer, cookie, val) LOCI_SHOW_checksum_128(writer, cookie, val)
-#define LOCI_SHOW_u32_buckets_size(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_entry_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_num_aux(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_checksum(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_egr_port_group_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf0(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf1(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf2(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf3(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf4(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf5(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf6(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf7(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_counter_id(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_desc_str_description(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_str64_name(writer, cookie, val) LOCI_SHOW_str64(writer, cookie, val)
-#define LOCI_SHOW_mac_local_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_nh_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_ipv4_src_ip(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_dst_ip(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_dscp_mode(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_dscp(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_ttl(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_vpn(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_rate_limit(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_flags(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_desc_str_image_checksum(write, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_startup_config_checksum(write, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_u16_bsn_tcp_flags(write, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u8_loglevel(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_vrf(write, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_vlan_xlate_port_group_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_mpls_bos(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-
 #endif /* _LOCI_SHOW_H_ */
diff --git a/c_gen/templates/of_object.c b/c_gen/templates/of_object.c
index 5647d81..596d79a 100644
--- a/c_gen/templates/of_object.c
+++ b/c_gen/templates/of_object.c
@@ -581,9 +581,6 @@
     if (loci_class_metadata[obj->object_id].wire_type_get != NULL) {
         of_object_id_t id;
         loci_class_metadata[obj->object_id].wire_type_get(obj, &id);
-        if (!of_wire_id_valid(id, base_object_id)) {
-            return OF_ERROR_PARSE;
-        }
         obj->object_id = id;
         /* Call the init function for this object type; do not push to wire */
         of_object_init_map[id]((of_object_t *)(obj), obj->version, -1, 0);
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
index 6cbb3a5..3544d80 100644
--- a/c_gen/type_maps.py
+++ b/c_gen/type_maps.py
@@ -25,126 +25,12 @@
 # EPL for the specific language governing permissions and limitations
 # under the EPL.
 
-#
-# Miscellaneous type information
-#
-# Define the map between sub-class types and wire values.  In each
-# case, an array indexed by wire version gives a hash from identifier
-# to wire value.
-#
-
-import c_gen.of_g_legacy as of_g
-import sys
 from generic_utils import *
-import loxi_utils.loxi_utils as loxi_utils
 import c_gen.loxi_utils_legacy as loxi_utils
 import loxi_globals
 
-invalid_type = "invalid_type"
-
-################################################################
-#
-# Define type data for inheritance classes:
-#   instructions, actions, queue properties and OXM
-#
-# Messages are not in this group; they're treated specially for now
-#
-# These are indexed by wire protocol number
-#
-################################################################
-
-instruction_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict()
-    }
-
-instruction_id_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict()
-    }
-
-action_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-action_id_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-queue_prop_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict()
-    }
-
-bsn_vport_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-oxm_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-hello_elem_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-table_feature_prop_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-meter_band_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-bsn_tlv_types = {
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(),
-    }
-
-# All inheritance data for non-messages
-inheritance_data = dict(
-    of_instruction = instruction_types,
-    of_instruction_id = instruction_id_types,
-    of_action = action_types,
-    of_action_id = action_id_types,
-    of_oxm = oxm_types,
-    of_queue_prop = queue_prop_types,
-    of_hello_elem = hello_elem_types,
-    of_table_feature_prop = table_feature_prop_types,
-    of_meter_band = meter_band_types,
-    # BSN specific inheritance extensions
-    of_bsn_vport = bsn_vport_types,
-    of_bsn_tlv = bsn_tlv_types,
-    )
+# map from inheritance root class name to set of subclass names
+inheritance_map = {}
 
 def class_is_virtual(cls):
     """
@@ -156,301 +42,20 @@
         return True
     return loxi_globals.unified.class_by_name(cls).virtual
 
-################################################################
-#
-# These are message types
-#
-################################################################
-
-# The hardcoded message types are for inheritance parents
-message_types = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(
-        error_msg               = 1,
-        experimenter            = 4,
-        flow_mod                = 14,
-        stats_request           = 16,
-        stats_reply             = 17,
-        ),
-
-    # version 1.1
-    of_g.VERSION_1_1:dict(
-        error_msg               = 1,
-        experimenter            = 4,
-        flow_mod                = 14,
-        group_mod               = 15,
-        stats_request           = 18,
-        stats_reply             = 19,
-        ),
-
-    # version 1.2
-    of_g.VERSION_1_2:dict(
-        error_msg               = 1,
-        experimenter            = 4,
-        flow_mod                = 14,
-        group_mod               = 15,
-        stats_request           = 18,
-        stats_reply             = 19,
-        ),
-
-    # version 1.3
-    of_g.VERSION_1_3:dict(
-        error_msg               = 1,
-        experimenter            = 4,
-        flow_mod                = 14,
-        group_mod               = 15,
-        stats_request           = 18,  # FIXME Multipart
-        stats_reply             = 19,
-        )
-    }
-
-################################################################
-#
-# These are other objects that have a notion of type but are
-# not (yet) promoted to objects with inheritance
-#
-################################################################
-
-stats_types = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(
-        desc = 0,
-        flow = 1,
-        aggregate = 2,
-        table = 3,
-        port = 4,
-        queue = 5,
-        experimenter = 0xffff
-        ),
-
-    # version 1.1
-    of_g.VERSION_1_1:dict(
-        desc = 0,
-        flow = 1,
-        aggregate = 2,
-        table = 3,
-        port = 4,
-        queue = 5,
-        group = 6,
-        group_desc = 7,
-        experimenter = 0xffff
-        ),
-
-    # version 1.2
-        of_g.VERSION_1_2:dict(
-        desc = 0,
-        flow = 1,
-        aggregate = 2,
-        table = 3,
-        port = 4,
-        queue = 5,
-        group = 6,
-        group_desc = 7,
-        group_features = 8,
-        experimenter = 0xffff
-        ),
-
-    # version 1.3
-        of_g.VERSION_1_3:dict(
-        desc = 0,
-        flow = 1,
-        aggregate = 2,
-        table = 3,
-        port = 4,
-        queue = 5,
-        group = 6,
-        group_desc = 7,
-        group_features = 8,
-        meter = 9,
-        meter_config = 10,
-        meter_features = 11,
-        table_features = 12,
-        port_desc = 13,
-        experimenter = 0xffff,
-        bsn_lacp = 0xffff,
-        bsn_switch_pipeline = 0xffff,
-        bsn_port_counter = 0xffff,
-        bsn_vlan_counter = 0xffff
-        )
-    }
-
-common_flow_mod_types = dict(
-    add = 0,
-    modify = 1,
-    modify_strict = 2,
-    delete = 3,
-    delete_strict = 4
-    )
-
-flow_mod_types = {
-    # version 1.0
-    of_g.VERSION_1_0:common_flow_mod_types,
-    of_g.VERSION_1_1:common_flow_mod_types,
-    of_g.VERSION_1_2:common_flow_mod_types,
-    of_g.VERSION_1_3:common_flow_mod_types
-    }
-
-# These do not translate to objects (yet)
-error_types = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(
-        hello_failed        = 0,
-        bad_request         = 1,
-        bad_action          = 2,
-        flow_mod_failed     = 3,
-        port_mod_failed     = 4,
-        queue_op_failed     = 5
-        ),
-
-    # version 1.1
-    of_g.VERSION_1_1:dict(
-        hello_failed         = 0,
-        bad_request          = 1,
-        bad_action           = 2,
-        bad_instruction      = 3,
-        bad_match            = 4,
-        flow_mod_failed      = 5,
-        group_mod_failed     = 6,
-        port_mod_failed      = 7,
-        table_mod_failed     = 8,
-        queue_op_failed      = 9,
-        switch_config_failed = 10
-        ),
-
-    # version 1.2
-    of_g.VERSION_1_2:dict(
-        hello_failed         = 0,
-        bad_request          = 1,
-        bad_action           = 2,
-        bad_instruction      = 3,
-        bad_match            = 4,
-        flow_mod_failed      = 5,
-        group_mod_failed     = 6,
-        port_mod_failed      = 7,
-        table_mod_failed     = 8,
-        queue_op_failed      = 9,
-        switch_config_failed = 10,
-        role_request_failed  = 11,
-        experimenter = 0xffff
-        ),
-
-    # version 1.3
-    of_g.VERSION_1_3:dict(
-        hello_failed         = 0,
-        bad_request          = 1,
-        bad_action           = 2,
-        bad_instruction      = 3,
-        bad_match            = 4,
-        flow_mod_failed      = 5,
-        group_mod_failed     = 6,
-        port_mod_failed      = 7,
-        table_mod_failed     = 8,
-        queue_op_failed      = 9,
-        switch_config_failed = 10,
-        role_request_failed  = 11,
-        meter_mod_failed     = 12,
-        table_features_failed= 13,
-        experimenter = 0xffff
-        )
-    }
-
-group_mod_types = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(),
-
-    # version 1.1
-    of_g.VERSION_1_1:dict(
-        add = 0,
-        modify = 1,
-        delete = 2
-        ),
-
-    # version 1.2
-    of_g.VERSION_1_2:dict(
-        add = 0,
-        modify = 1,
-        delete = 2
-        ),
-
-    # version 1.3
-    of_g.VERSION_1_3:dict(
-        add = 0,
-        modify = 1,
-        delete = 2
-        )
-    }
-
-################################################################
-#
-# type_val is the primary data structure that maps an
-# (class_name, version) pair to the wire data type value
-#
-################################################################
-
-type_val = dict()
-inheritance_map = dict()
+def class_is_inheritance_root(cls):
+    return cls in inheritance_map
 
 def generate_maps():
-    for parent, versioned in inheritance_data.items():
-        inheritance_map[parent] = set()
-        for ver, subclasses in versioned.items():
-            for subcls in subclasses:
-                inheritance_map[parent].add(subcls)
+    for version, protocol in loxi_globals.ir.items():
+        wire_version = version.wire_version
+        for ofclass in protocol.classes:
+            root = ofclass.inheritance_root()
+            if not root or root == ofclass or root.name == "of_header":
+                continue
 
-    for version, classes in message_types.items():
-        for cls in classes:
-            name = "of_" + cls
-            type_val[(name, version)] = classes[cls]
-
-    for parent, versioned in inheritance_data.items():
-        for version, subclasses in versioned.items():
-            for subcls, value in subclasses.items():
-                name = parent + "_" + subcls
-                type_val[(name, version)] = value
-
-    # Special case OF-1.2 match type
-    type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
-    type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
-
-# Utility function
-def dict_to_array(d, m_val, def_val=-1):
-    """
-    Given a dictionary, d, with each value a small integer,
-    produce an array indexed by the integer whose value is the key.
-    @param d The dictionary
-    @param m_val Ignore values greater than m_val
-    @param def_val The default value (for indices not in range of d)
-    """
-
-    # Get the max value in range for hash
-    max_val = 0
-    for key in d:
-        if (d[key] > max_val) and (d[key] < m_val):
-            max_val = d[key]
-    ar = []
-    for x in range(0, max_val + 1):
-        ar.append(def_val)
-    for key in d:
-        if (d[key] < m_val):
-            ar[d[key]] = key
-    return ar
-
-def type_array_len(version_indexed, max_val):
-    """
-    Given versioned information about a type, calculate how long
-    the unified array should be.
-
-    @param version_indexed A dict indexed by version. Each value is a
-    dict indexed by a name and whose value is an integer
-    @param max_val Ignore values greater than this for length calcs
-    """
-    # First, find the max length of all arrays
-    arr_len = 0
-    for version, val_dict in version_indexed.items():
-        ar = dict_to_array(val_dict, max_val, invalid_type)
-        if arr_len < len(ar):
-            arr_len = len(ar)
-    return arr_len
+            if root.name not in inheritance_map:
+                inheritance_map[root.name] = set()
+            inheritance_map[root.name].add(ofclass.name)
 
 def sub_class_map(base_type, version):
     """
@@ -461,99 +66,10 @@
     if base_type not in inheritance_map:
         return rv
 
-    for instance in inheritance_map[base_type]:
-        subcls = loxi_utils.instance_to_class(instance, base_type)
+    for subcls in inheritance_map[base_type]:
         if not loxi_utils.class_in_version(subcls, version):
             continue
+        instance = loxi_utils.class_to_instance(subcls, base_type)
         rv.append((instance, subcls))
 
     return rv
-
-################################################################
-#
-# Extension related data and functions
-#
-################################################################
-
-# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
-# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
-extension_message_subtype = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(  # Version 1.0 extensions
-        bsn = {   # BSN extensions; indexed by class name, value is subtype
-            },
-        nicira = {   # Nicira extensions, value is subtype
-            },
-        ),
-    of_g.VERSION_1_1:dict(  # Version 1.0 extensions
-        bsn = {   # BSN extensions; indexed by class name, value is subtype
-            },
-        ),
-    of_g.VERSION_1_2:dict(  # Version 1.0 extensions
-        bsn = {   # BSN extensions; indexed by class name, value is subtype
-            },
-        ),
-    of_g.VERSION_1_3:dict(  # Version 1.0 extensions
-        bsn = {   # BSN extensions; indexed by class name, value is subtype
-            },
-        ),
-}
-
-# Set to empty dict if no extension actions defined
-# Per OF Version, per experimenter, map actions to subtype
-extension_action_subtype = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(  # Version 1.0 extensions
-        bsn = {   # of_action_bsn_
-            },
-        nicira = {   # of_action_nicira_
-            }
-        ),
-    of_g.VERSION_1_1:dict(  # Version 1.0 extensions
-        bsn = {   # of_action_bsn_
-            },
-        nicira = {   # of_action_nicira_
-            }
-        ),
-    of_g.VERSION_1_2:dict(  # Version 1.0 extensions
-        bsn = {   # of_action_bsn_
-            },
-        nicira = {   # of_action_nicira_
-            }
-        ),
-    of_g.VERSION_1_3:dict(  # Version 1.0 extensions
-        bsn = {   # of_action_bsn_
-            },
-        nicira = {   # of_action_nicira_
-            }
-        ),
-}
-
-# Set to empty dict if no extension actions defined
-# Per OF Version, per experimenter, map actions to subtype
-extension_action_id_subtype = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(  # Version 1.3 extensions
-        bsn = {   # of_action_bsn_
-            },
-        nicira = {   # of_action_nicira_
-            }
-        ),
-}
-
-# Set to empty dict if no extension instructions defined
-extension_instruction_subtype = {
-    # version 1.0
-    of_g.VERSION_1_0:dict(),
-    of_g.VERSION_1_1:dict(),
-    of_g.VERSION_1_2:dict(),
-    of_g.VERSION_1_3:dict(
-        bsn = {   # of_instruction_bsn_
-            },
-        nicira = {   # of_instruction_nicira_
-            }
-        ),
-}
diff --git a/loxi_ir/ir.py b/loxi_ir/ir.py
index 0e95473..7b9a0b6 100644
--- a/loxi_ir/ir.py
+++ b/loxi_ir/ir.py
@@ -145,6 +145,15 @@
     def is_subclassof(self, super_class_name):
         return self.name != super_class_name and self.is_instanceof(super_class_name)
 
+    def inheritance_root(self):
+        if not self.superclass:
+            if self.virtual:
+                return self
+            else:
+                return None
+        else:
+            return self.superclass.inheritance_root()
+
     @property
     def is_message(self):
         return self.is_instanceof("of_header")
diff --git a/openflow_input/bsn_tlv b/openflow_input/bsn_tlv
index cc81b96..3e52d02 100644
--- a/openflow_input/bsn_tlv
+++ b/openflow_input/bsn_tlv
@@ -274,3 +274,69 @@
     uint16_t length;
     uint64_t value;
 };
+
+struct of_bsn_tlv_actor_system_priority: of_bsn_tlv {
+    uint16_t type == 40;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_actor_system_mac: of_bsn_tlv {
+    uint16_t type == 41;
+    uint16_t length;
+    of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_actor_port_priority: of_bsn_tlv {
+    uint16_t type == 42;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_actor_port_num: of_bsn_tlv {
+    uint16_t type == 43;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_actor_key: of_bsn_tlv {
+    uint16_t type == 44;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_convergence_status: of_bsn_tlv {
+    uint16_t type == 45;
+    uint16_t length;
+    uint8_t value;
+};
+
+struct of_bsn_tlv_partner_system_priority: of_bsn_tlv {
+    uint16_t type == 47;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_partner_system_mac: of_bsn_tlv {
+    uint16_t type == 48;
+    uint16_t length;
+    of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_partner_port_priority: of_bsn_tlv {
+    uint16_t type == 49;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_partner_port_num: of_bsn_tlv {
+    uint16_t type == 50;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_partner_key: of_bsn_tlv {
+    uint16_t type == 51;
+    uint16_t length;
+    uint16_t value;
+};