loxi_frontend: move classes only used by c to c_gen

 - flags
 - identifiers
 - match
 - translation
 - type_maps

were only used by the c backend. I'm moving them to c_gen to
unclutter the loxi_front_end space (and updating references
in the c backend)
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index 798f5a4..e35ee8d 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -34,13 +34,11 @@
 import of_g
 import c_match
 from generic_utils import *
-import c_gen.c_type_maps as c_type_maps
-import loxi_front_end.type_maps as type_maps
-import loxi_front_end.flags as flags
-import loxi_utils.loxi_utils as loxi_utils
-import loxi_front_end.identifiers as identifiers
+from c_gen import flags, type_maps, c_type_maps
+import c_gen.loxi_utils_legacy as loxi_utils
+from c_gen.loxi_utils_legacy import config_check
 
-# 'property' is for queues. Could be trouble
+import c_gen.identifiers as identifiers
 
 
 ################################################################
diff --git a/c_gen/c_dump_gen.py b/c_gen/c_dump_gen.py
index 837ff78..9d487e2 100644
--- a/c_gen/c_dump_gen.py
+++ b/c_gen/c_dump_gen.py
@@ -34,12 +34,12 @@
 
 import sys
 import of_g
-import loxi_front_end.match as match
-import loxi_front_end.flags as flags
+import c_gen.match as match
+import c_gen.flags as flags
 from generic_utils import *
-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 c_gen.type_maps as type_maps
+import c_gen.loxi_utils_legacy as loxi_utils
+import c_gen.identifiers as identifiers
 from c_test_gen import var_name_map
 
 def gen_obj_dump_h(out, name):
diff --git a/c_gen/c_match.py b/c_gen/c_match.py
index 4001612..a45090a 100644
--- a/c_gen/c_match.py
+++ b/c_gen/c_match.py
@@ -40,8 +40,8 @@
 # takes mask
 
 import sys
-import of_g
-import loxi_front_end.match as match
+import c_gen.of_g_legacy as of_g
+import c_gen.match as match
 import c_code_gen
 
 def match_c_top_matter(out, name):
diff --git a/c_gen/c_show_gen.py b/c_gen/c_show_gen.py
index 0ec81b4..fe3e3dc 100644
--- a/c_gen/c_show_gen.py
+++ b/c_gen/c_show_gen.py
@@ -34,12 +34,13 @@
 
 import sys
 import of_g
-import loxi_front_end.match as match
-import loxi_front_end.flags as flags
+import c_gen.match as match
+import c_gen.flags as flags
 from generic_utils import *
-import loxi_front_end.type_maps as type_maps
+import c_gen.type_maps as type_maps
 import loxi_utils.loxi_utils as loxi_utils
-import loxi_front_end.identifiers as identifiers
+import c_gen.loxi_utils_legacy as loxi_utils
+import c_gen.identifiers as identifiers
 from c_test_gen import var_name_map
 
 def gen_obj_show_h(out, name):
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index d237cfe..c9c8245 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -60,12 +60,12 @@
 
 import sys
 import of_g
-import loxi_front_end.match as match
-import loxi_front_end.flags as flags
+import c_gen.match as match
+import c_gen.flags as flags
 from generic_utils import *
-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 c_gen.type_maps as type_maps
+import c_gen.loxi_utils_legacy as loxi_utils
+import c_gen.identifiers as identifiers
 import util
 import test_data
 
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index 8883193..69dc804 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -32,7 +32,7 @@
 import of_g
 import sys
 from generic_utils import *
-import loxi_front_end.type_maps as type_maps
+import c_gen.type_maps as type_maps
 
 
 # Some number larger than small type values, but less then
diff --git a/c_gen/c_validator_gen.py b/c_gen/c_validator_gen.py
index 2930724..e799918 100644
--- a/c_gen/c_validator_gen.py
+++ b/c_gen/c_validator_gen.py
@@ -34,12 +34,13 @@
 
 import sys
 import of_g
-import loxi_front_end.match as match
-import loxi_front_end.flags as flags
+import c_gen.match as match
+import c_gen.flags as flags
 from generic_utils import *
-import loxi_front_end.type_maps as type_maps
+import c_gen.type_maps as type_maps
 import loxi_utils.loxi_utils as loxi_utils
-import loxi_front_end.identifiers as identifiers
+import c_gen.loxi_utils_legacy as loxi_utils
+import c_gen.identifiers as identifiers
 from c_test_gen import var_name_map
 from c_code_gen import v3_match_offset_get
 
diff --git a/c_gen/flags.py b/c_gen/flags.py
new file mode 100644
index 0000000..1fa4ae5
--- /dev/null
+++ b/c_gen/flags.py
@@ -0,0 +1,75 @@
+# 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.
+
+"""
+This file needs significant work and normalization.  We need a better
+representation for flags, associating them to variables, and associating
+them to OF versions.
+
+@fixme Most of this will be going away soon
+"""
+
+import sys
+import copy
+import type_maps
+import c_gen.of_g_legacy as of_g
+import re
+
+# These mark idents as _not_ flags and have precedence
+non_flag_rules = [
+    "OF_CONFIG_FRAG_NORMAL",
+    "OF_FLOW_MOD_FAILED_BAD_FLAGS",
+    "OF_SWITCH_CONFIG_FAILED_BAD_FLAGS",
+    "OF_PORT_STATE_FLAG_STP_LISTEN",
+    "OF_TABLE_CONFIG_TABLE_MISS_CONTROLLER",
+    ]
+
+# These mark idents as flags
+flag_rules = [
+    "OF_CONFIG_",
+    "OF_TABLE_CONFIG_",
+    ]
+
+def ident_is_flag(ident):
+    """
+    Return True if ident should be treated as a flag
+    """
+
+    # Do negative matches first
+    for entry in non_flag_rules:
+        if re.match(entry, ident):
+            return False
+
+    # General rule, if it says flag it is (unless indicated above)
+    if ident.find("FLAG") >= 0:
+        return True
+
+    for entry in flag_rules:
+        if re.match(entry, ident):
+            return True
+
+    return False
diff --git a/c_gen/identifiers.py b/c_gen/identifiers.py
new file mode 100644
index 0000000..5862967
--- /dev/null
+++ b/c_gen/identifiers.py
@@ -0,0 +1,83 @@
+# 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.
+
+##
+# @brief Process identifiers for updating of_g.identifiers
+#
+
+import sys
+from generic_utils import *
+
+##
+# The value to use when an identifier is not defined for a version
+UNDEFINED_IDENT_VALUE = 0
+
+def add_identifier(name, ofp_name, ofp_group, value, version, all_idents, idents_by_group):
+    assert(isinstance(value, (int,long)))
+    if name in all_idents:
+        all_idents[name]["values_by_version"][version] = value
+        if ((all_idents[name]["ofp_name"] != ofp_name or
+            all_idents[name]["ofp_group"] != ofp_group) and
+            ofp_name.find("OFPP_") != 0):
+            log("""
+NOTE: Identifier %s has different ofp name or group in version %s
+From ofp name %s, group %s to name %s, group %s.
+This could indicate a name collision in LOXI identifier translation.
+""" % (name, str(version), all_idents[name]["ofp_name"],
+    all_idents[name]["ofp_group"], ofp_name, ofp_group))
+            # Update stuff assuming newer versions processed later
+            all_idents[name]["ofp_name"] = ofp_name
+            all_idents[name]["ofp_group"] = ofp_group
+
+    else: # New name
+        all_idents[name] = dict(
+            values_by_version = {version:value},
+            common_value = value,
+            ofp_name = ofp_name,
+            ofp_group = ofp_group
+            )
+        if ofp_group not in idents_by_group:
+            idents_by_group[ofp_group] = []
+        if name not in idents_by_group[ofp_group]:
+            idents_by_group[ofp_group].append(name)
+
+def all_versions_agree(all_idents, version_list, name):
+    val_list = all_idents[name]["values_by_version"]
+    for version in version_list:
+        if not version in val_list:
+            return False
+        if str(val_list[version]) != str(all_idents[name]["common_value"]):
+            return False
+    return True
+
+def defined_versions_agree(all_idents, version_list, name):
+    val_list = all_idents[name]["values_by_version"]
+    for version in version_list:
+        if version in val_list:
+            if str(val_list[version]) != str(all_idents[name]["common_value"]):
+                return False
+    return True
diff --git a/c_gen/loci_utils.py b/c_gen/loci_utils.py
new file mode 100644
index 0000000..bc3092f
--- /dev/null
+++ b/c_gen/loci_utils.py
@@ -0,0 +1,267 @@
+import c_gen.of_g_legacy as of_g
+
+def class_signature(members):
+    """
+    Generate a signature string for a class in canonical form
+
+    @param cls The class whose signature is to be generated
+    """
+    return ";".join([",".join([x["m_type"], x["name"], str(x["offset"])])
+                     for x in members])
+
+def type_dec_to_count_base(m_type):
+    """
+    Resolve a type declaration like uint8_t[4] to a count (4) and base_type
+    (uint8_t)
+
+    @param m_type The string type declaration to process
+    """
+    count = 1
+    chk_ar = m_type.split('[')
+    if len(chk_ar) > 1:
+        count_str = chk_ar[1].split(']')[0]
+        if count_str in of_g.ofp_constants:
+            count = of_g.ofp_constants[count_str]
+        else:
+            count = int(count_str)
+        base_type = chk_ar[0]
+    else:
+        base_type = m_type
+    return count, base_type
+
+def list_to_entry_type(cls):
+    """
+    Return the entry type for a list
+    """
+    slen = len("of_list_")
+    return "of_" + cls[slen:]
+
+def type_to_short_name(m_type):
+    if m_type in of_g.of_base_types:
+        tname = of_g.of_base_types[m_type]["short_name"]
+    elif m_type in of_g.of_mixed_types:
+        tname = of_g.of_mixed_types[m_type]["short_name"]
+    else:
+        tname = "unknown"
+    return tname
+
+def type_to_name_type(cls, member_name):
+    """
+    Generate the root name of a member for accessor functions, etc
+    @param cls The class name
+    @param member_name The member name
+    """
+    members = of_g.unified[cls]["union"]
+    if not member_name in members:
+        debug("Error:  %s is not in class %s for acc_name defn" %
+              (member_name, cls))
+        os.exit()
+
+    mem = members[member_name]
+    m_type = mem["m_type"]
+    id = mem["memid"]
+    tname = type_to_short_name(m_type)
+
+    return "o%d_m%d_%s" % (of_g.unified[cls]["object_id"], id, tname)
+
+
+def member_to_index(m_name, members):
+    """
+    Given a member name, return the index in the members dict
+    @param m_name The name of the data member to search for
+    @param members The dict of members
+    @return Index if found, -1 not found
+
+    Note we could generate an index when processing the original input
+    """
+    count = 0
+    for d in members:
+        if d["name"] == m_name:
+            return count
+        count += 1
+    return -1
+
+def member_base_type(cls, m_name):
+    """
+    Map a member to its of_ type
+    @param cls The class name
+    @param m_name The name of the member being gotten
+    @return The of_ type of the member
+    """
+    rv = of_g.unified[cls]["union"][m_name]["m_type"]
+    if rv[-2:] == "_t":
+        return rv
+    return rv + "_t"
+
+def member_type_is_octets(cls, m_name):
+    return member_base_type(cls, m_name) == "of_octets_t"
+
+def member_returns_val(cls, m_name):
+    """
+    Should get accessor return a value rather than void
+    @param cls The class name
+    @param m_name The member name
+    @return True if of_g config and the specific member allow a
+    return value.  Otherwise False
+    """
+    m_type = of_g.unified[cls]["union"][m_name]["m_type"]
+    return (config_check("get_returns") =="value" and
+            m_type in of_g.of_scalar_types)
+
+def config_check(str, dictionary = of_g.code_gen_config):
+    """
+    Return config value if in dictionary; else return False.
+    @param str The lookup index
+    @param dictionary The dict to check; use code_gen_config if None
+    """
+
+    if str in dictionary:
+        return dictionary[str]
+
+    return False
+
+def h_file_to_define(name):
+    """
+    Convert a .h file name to the define used for the header
+    """
+    h_name = name[:-2].upper()
+    h_name = "_" + h_name + "_H_"
+    return h_name
+
+def type_to_cof_type(m_type):
+    if m_type in of_g.of_base_types:
+        if "cof_type" in of_g.of_base_types[m_type]:
+            return of_g.of_base_types[m_type]["cof_type"]
+    return m_type
+
+
+def member_is_scalar(cls, m_name):
+    return of_g.unified[cls]["union"][m_name]["m_type"] in of_g.of_scalar_types
+
+def type_is_scalar(m_type):
+    return m_type in of_g.of_scalar_types
+
+def skip_member_name(name):
+    return name.find("pad") == 0 or name in of_g.skip_members
+
+def enum_name(cls):
+    """
+    Return the name used for an enum identifier for the given class
+    @param cls The class name
+    """
+    return cls.upper()
+
+def class_in_version(cls, ver):
+    """
+    Return boolean indicating if cls is defined for wire version ver
+    """
+
+    return (cls, ver) in of_g.base_length
+
+def instance_to_class(instance, parent):
+    """
+    Return the name of the class for an instance of inheritance type parent
+    """
+    return parent + "_" + instance
+
+def sub_class_to_var_name(cls):
+    """
+    Given a subclass name like of_action_output, generate the
+    name of a variable like 'output'
+    @param cls The class name
+    """
+    pass
+
+def class_is_var_len(cls, version):
+    # Match is special case.  Only version 1.2 (wire version 3) is var
+    if cls == "of_match":
+        return version == 3
+
+    return not (cls, version) in of_g.is_fixed_length
+
+def base_type_to_length(base_type, version):
+    if base_type + "_t" in of_g.of_base_types:
+        inst_len = of_g.of_base_types[base_type + "_t"]["bytes"]
+    else:
+        inst_len = of_g.base_length[(base_type, version)]
+
+def version_to_name(version):
+    """
+    Convert an integer version to the C macro name
+    """
+    return "OF_" + of_g.version_names[version]
+
+##
+# Is class a flow modify of some sort?
+
+def cls_is_flow_mod(cls):
+    return cls in ["of_flow_mod", "of_flow_modify", "of_flow_add", "of_flow_delete",
+                   "of_flow_modify_strict", "of_flow_delete_strict"]
+
+def all_member_types_get(cls, version):
+    """
+    Get the members and list of types for members of a given class
+    @param cls The class name to process
+    @param version The version for the class
+    """
+    member_types = []
+
+    if not version in of_g.unified[cls]:
+        return ([], [])
+
+    if "use_version" in of_g.unified[cls][version]:
+        v = of_g.unified[cls][version]["use_version"]
+        members = of_g.unified[cls][v]["members"]
+    else:
+        members = of_g.unified[cls][version]["members"]
+    # Accumulate variables that are supported
+    for member in members:
+        m_type = member["m_type"]
+        m_name = member["name"]
+        if skip_member_name(m_name):
+            continue
+        if not m_type in member_types:
+            member_types.append(m_type)
+
+    return (members, member_types)
+
+def list_name_extract(list_type):
+    """
+    Return the base name for a list object of the given type
+    @param list_type The type of the list as appears in the input,
+    for example list(of_port_desc_t).
+    @return A pair, (list-name, base-type) where list-name is the
+    base name for the list, for example of_list_port_desc, and base-type
+    is the type of list elements like of_port_desc_t
+    """
+    base_type = list_type[5:-1]
+    list_name = base_type
+    if list_name.find("of_") == 0:
+        list_name = list_name[3:]
+    if list_name[-2:] == "_t":
+        list_name = list_name[:-2]
+    list_name = "of_list_" + list_name
+    return (list_name, base_type)
+
+def version_to_name(version):
+    """
+    Convert an integer version to the C macro name
+    """
+    return "OF_" + of_g.version_names[version]
+
+def gen_c_copy_license(out):
+    """
+    Generate the top comments for copyright and license
+    """
+    import c_gen.util
+    c_gen.util.render_template(out, '_copyright.c')
+
+def accessor_returns_error(a_type, m_type):
+    is_var_len = (not type_is_scalar(m_type)) and \
+        [x for x in of_g.of_version_range if class_is_var_len(m_type[:-2], x)] != []
+    if a_type == "set" and is_var_len:
+        return True
+    elif m_type == "of_match_t":
+        return True
+    else:
+        return False
diff --git a/c_gen/loxi_utils_legacy.py b/c_gen/loxi_utils_legacy.py
new file mode 100644
index 0000000..47b1430
--- /dev/null
+++ b/c_gen/loxi_utils_legacy.py
@@ -0,0 +1,545 @@
+# 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.
+
+"""
+@brief Utilities involving LOXI naming conventions
+
+Utility functions for OpenFlow class generation
+
+These may need to be sorted out into language specific functions
+"""
+
+import sys
+import c_gen.of_g_legacy as of_g
+import tenjin
+from generic_utils import find, memoize
+
+def class_signature(members):
+    """
+    Generate a signature string for a class in canonical form
+
+    @param cls The class whose signature is to be generated
+    """
+    return ";".join([",".join([x["m_type"], x["name"], str(x["offset"])])
+                     for x in members])
+
+def type_dec_to_count_base(m_type):
+    """
+    Resolve a type declaration like uint8_t[4] to a count (4) and base_type
+    (uint8_t)
+
+    @param m_type The string type declaration to process
+    """
+    count = 1
+    chk_ar = m_type.split('[')
+    if len(chk_ar) > 1:
+        count_str = chk_ar[1].split(']')[0]
+        if count_str in of_g.ofp_constants:
+            count = of_g.ofp_constants[count_str]
+        else:
+            count = int(count_str)
+        base_type = chk_ar[0]
+    else:
+        base_type = m_type
+    return count, base_type
+
+##
+# Class types:
+#
+# Virtual
+#    A virtual class is one which does not have an explicit wire
+#    representation.  For example, an inheritance super class
+#    or a list type.
+#
+# List
+#    A list of objects of some other type
+#
+# TLV16
+#    The wire represenation starts with 16-bit type and length fields
+#
+# OXM
+#    An extensible match object
+#
+# Message
+#    A top level OpenFlow message
+#
+#
+
+def class_is_message(cls):
+    """
+    Return True if cls is a message object based on info in unified
+    """
+    return "xid" in of_g.unified[cls]["union"] and cls != "of_header"
+
+def class_is_tlv16(cls):
+    """
+    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
+        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
+    return False
+
+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"]
+
+def class_is_oxm(cls):
+    """
+    Return True if cls_name is an OXM object
+    """
+    if cls.find("of_oxm") == 0:
+        return True
+    return False
+
+def class_is_action(cls):
+    """
+    Return True if cls_name is an action object
+
+    Note that action_id is not an action object, though it has
+    the same header.  It looks like an action header, but the type
+    is used to identify a kind of action, it does not indicate the
+    type of the object following.
+    """
+    if cls.find("of_action_id") == 0:
+        return False
+    if cls.find("of_action") == 0:
+        return True
+
+    # For each vendor, check for vendor specific action
+    for exp in of_g.experimenter_name_to_id:
+        if cls.find("of_action" + exp) == 0:
+            return True
+
+    return False
+
+def class_is_action_id(cls):
+    """
+    Return True if cls_name is an action object
+
+    Note that action_id is not an action object, though it has
+    the same header.  It looks like an action header, but the type
+    is used to identify a kind of action, it does not indicate the
+    type of the object following.
+    """
+    if cls.find("of_action_id") == 0:
+        return True
+
+    # For each vendor, check for vendor specific action
+    for exp in of_g.experimenter_name_to_id:
+        if cls.find("of_action_id_" + exp) == 0:
+            return True
+
+    return False
+
+def class_is_instruction(cls):
+    """
+    Return True if cls_name is an instruction object
+    """
+    if cls.find("of_instruction") == 0:
+        return True
+
+    # For each vendor, check for vendor specific action
+    for exp in of_g.experimenter_name_to_id:
+        if cls.find("of_instruction_" + exp) == 0:
+            return True
+
+    return False
+
+def class_is_meter_band(cls):
+    """
+    Return True if cls_name is an instruction object
+    """
+    # meter_band_stats is not a member of meter_band class hierarchy
+    if cls.find("of_meter_band_stats") == 0:
+        return False
+    if cls.find("of_meter_band") == 0:
+        return True
+    return False
+
+def class_is_hello_elem(cls):
+    """
+    Return True if cls_name is an instruction object
+    """
+    if cls.find("of_hello_elem") == 0:
+        return True
+    return False
+
+def class_is_queue_prop(cls):
+    """
+    Return True if cls_name is a queue_prop object
+    """
+    if cls.find("of_queue_prop") == 0:
+        return True
+
+    # For each vendor, check for vendor specific action
+    for exp in of_g.experimenter_name_to_id:
+        if cls.find("of_queue_prop_" + exp) == 0:
+            return True
+
+    return False
+
+def class_is_table_feature_prop(cls):
+    """
+    Return True if cls_name is a queue_prop object
+    """
+    if cls.find("of_table_feature_prop") == 0:
+        return True
+    return False
+
+def class_is_stats_message(cls):
+    """
+    Return True if cls_name is a message object based on info in unified
+    """
+
+    return "stats_type" in of_g.unified[cls]["union"]
+
+def class_is_list(cls):
+    """
+    Return True if cls_name is a list object
+    """
+    return (cls.find("of_list_") == 0)
+
+def type_is_of_object(m_type):
+    """
+    Return True if m_type is an OF object type
+    """
+    # Remove _t from the type id and see if key for unified class
+    if m_type[-2:] == "_t":
+        m_type = m_type[:-2]
+    return m_type in of_g.unified
+
+def list_to_entry_type(cls):
+    """
+    Return the entry type for a list
+    """
+    slen = len("of_list_")
+    return "of_" + cls[slen:]
+
+def type_to_short_name(m_type):
+    if m_type in of_g.of_base_types:
+        tname = of_g.of_base_types[m_type]["short_name"]
+    elif m_type in of_g.of_mixed_types:
+        tname = of_g.of_mixed_types[m_type]["short_name"]
+    else:
+        tname = "unknown"
+    return tname
+
+def type_to_name_type(cls, member_name):
+    """
+    Generate the root name of a member for accessor functions, etc
+    @param cls The class name
+    @param member_name The member name
+    """
+    members = of_g.unified[cls]["union"]
+    if not member_name in members:
+        debug("Error:  %s is not in class %s for acc_name defn" %
+              (member_name, cls))
+        os.exit()
+
+    mem = members[member_name]
+    m_type = mem["m_type"]
+    id = mem["memid"]
+    tname = type_to_short_name(m_type)
+
+    return "o%d_m%d_%s" % (of_g.unified[cls]["object_id"], id, tname)
+
+
+def member_to_index(m_name, members):
+    """
+    Given a member name, return the index in the members dict
+    @param m_name The name of the data member to search for
+    @param members The dict of members
+    @return Index if found, -1 not found
+
+    Note we could generate an index when processing the original input
+    """
+    count = 0
+    for d in members:
+        if d["name"] == m_name:
+            return count
+        count += 1
+    return -1
+
+def member_base_type(cls, m_name):
+    """
+    Map a member to its of_ type
+    @param cls The class name
+    @param m_name The name of the member being gotten
+    @return The of_ type of the member
+    """
+    rv = of_g.unified[cls]["union"][m_name]["m_type"]
+    if rv[-2:] == "_t":
+        return rv
+    return rv + "_t"
+
+def member_type_is_octets(cls, m_name):
+    return member_base_type(cls, m_name) == "of_octets_t"
+
+def member_returns_val(cls, m_name):
+    """
+    Should get accessor return a value rather than void
+    @param cls The class name
+    @param m_name The member name
+    @return True if of_g config and the specific member allow a
+    return value.  Otherwise False
+    """
+    m_type = of_g.unified[cls]["union"][m_name]["m_type"]
+    return (config_check("get_returns") =="value" and
+            m_type in of_g.of_scalar_types)
+
+def config_check(str, dictionary = of_g.code_gen_config):
+    """
+    Return config value if in dictionary; else return False.
+    @param str The lookup index
+    @param dictionary The dict to check; use code_gen_config if None
+    """
+
+    if str in dictionary:
+        return dictionary[str]
+
+    return False
+
+def h_file_to_define(name):
+    """
+    Convert a .h file name to the define used for the header
+    """
+    h_name = name[:-2].upper()
+    h_name = "_" + h_name + "_H_"
+    return h_name
+
+def type_to_cof_type(m_type):
+    if m_type in of_g.of_base_types:
+        if "cof_type" in of_g.of_base_types[m_type]:
+            return of_g.of_base_types[m_type]["cof_type"]
+    return m_type
+
+
+def member_is_scalar(cls, m_name):
+    return of_g.unified[cls]["union"][m_name]["m_type"] in of_g.of_scalar_types
+
+def type_is_scalar(m_type):
+    return m_type in of_g.of_scalar_types
+
+def skip_member_name(name):
+    return name.find("pad") == 0 or name in of_g.skip_members
+
+def enum_name(cls):
+    """
+    Return the name used for an enum identifier for the given class
+    @param cls The class name
+    """
+    return cls.upper()
+
+def class_in_version(cls, ver):
+    """
+    Return boolean indicating if cls is defined for wire version ver
+    """
+
+    return (cls, ver) in of_g.base_length
+
+def instance_to_class(instance, parent):
+    """
+    Return the name of the class for an instance of inheritance type parent
+    """
+    return parent + "_" + instance
+
+def sub_class_to_var_name(cls):
+    """
+    Given a subclass name like of_action_output, generate the
+    name of a variable like 'output'
+    @param cls The class name
+    """
+    pass
+
+def class_is_var_len(cls, version):
+    # Match is special case.  Only version 1.2 (wire version 3) is var
+    if cls == "of_match":
+        return version == 3
+
+    return not (cls, version) in of_g.is_fixed_length
+
+def base_type_to_length(base_type, version):
+    if base_type + "_t" in of_g.of_base_types:
+        inst_len = of_g.of_base_types[base_type + "_t"]["bytes"]
+    else:
+        inst_len = of_g.base_length[(base_type, version)]
+
+def version_to_name(version):
+    """
+    Convert an integer version to the C macro name
+    """
+    return "OF_" + of_g.version_names[version]
+
+##
+# Is class a flow modify of some sort?
+
+def cls_is_flow_mod(cls):
+    return cls in ["of_flow_mod", "of_flow_modify", "of_flow_add", "of_flow_delete",
+                   "of_flow_modify_strict", "of_flow_delete_strict"]
+
+
+def all_member_types_get(cls, version):
+    """
+    Get the members and list of types for members of a given class
+    @param cls The class name to process
+    @param version The version for the class
+    """
+    member_types = []
+
+    if not version in of_g.unified[cls]:
+        return ([], [])
+
+    if "use_version" in of_g.unified[cls][version]:
+        v = of_g.unified[cls][version]["use_version"]
+        members = of_g.unified[cls][v]["members"]
+    else:
+        members = of_g.unified[cls][version]["members"]
+    # Accumulate variables that are supported
+    for member in members:
+        m_type = member["m_type"]
+        m_name = member["name"]
+        if skip_member_name(m_name):
+            continue
+        if not m_type in member_types:
+            member_types.append(m_type)
+
+    return (members, member_types)
+
+def list_name_extract(list_type):
+    """
+    Return the base name for a list object of the given type
+    @param list_type The type of the list as appears in the input,
+    for example list(of_port_desc_t).
+    @return A pair, (list-name, base-type) where list-name is the
+    base name for the list, for example of_list_port_desc, and base-type
+    is the type of list elements like of_port_desc_t
+    """
+    base_type = list_type[5:-1]
+    list_name = base_type
+    if list_name.find("of_") == 0:
+        list_name = list_name[3:]
+    if list_name[-2:] == "_t":
+        list_name = list_name[:-2]
+    list_name = "of_list_" + list_name
+    return (list_name, base_type)
+
+def version_to_name(version):
+    """
+    Convert an integer version to the C macro name
+    """
+    return "OF_" + of_g.version_names[version]
+
+def gen_c_copy_license(out):
+    """
+    Generate the top comments for copyright and license
+    """
+    import c_gen.util
+    c_gen.util.render_template(out, '_copyright.c')
+
+def accessor_returns_error(a_type, m_type):
+    is_var_len = (not type_is_scalar(m_type)) and \
+        [x for x in of_g.of_version_range if class_is_var_len(m_type[:-2], x)] != []
+    if a_type == "set" and is_var_len:
+        return True
+    elif m_type == "of_match_t":
+        return True
+    else:
+        return False
+
+def render_template(out, name, path, context, prefix = None):
+    """
+    Render a template using tenjin.
+    out: a file-like object
+    name: name of the template
+    path: array of directories to search for the template
+    context: dictionary of variables to pass to the template
+    prefix: optional prefix to use for embedding (for other languages than python)
+    """
+    pp = [ tenjin.PrefixedLinePreprocessor(prefix=prefix) if prefix else tenjin.PrefixedLinePreprocessor() ] # support "::" syntax
+    template_globals = { "to_str": str, "escape": str } # disable HTML escaping
+    engine = TemplateEngine(path=path, pp=pp)
+    out.write(engine.render(name, context, template_globals))
+
+def render_static(out, name, path):
+    """
+    Write out a static template.
+    out: a file-like object
+    name: name of the template
+    path: array of directories to search for the template
+    """
+    # Reuse the tenjin logic for finding the template
+    template_filename = tenjin.FileSystemLoader().find(name, path)
+    if not template_filename:
+        raise ValueError("template %s not found" % name)
+    with open(template_filename) as infile:
+        out.write(infile.read())
+
+@memoize
+def lookup_ir_wiretype(oftype, version):
+    """ if of is a reference to an enum in ir, resolve it to the wiretype
+        declared in that enum. Else return oftype """
+    enums = of_g.ir[version].enums
+    enum = find(lambda e: e.name == oftype, enums)
+    if enum and 'wire_type' in enum.params:
+        return enum.params['wire_type']
+    else:
+        return oftype
+
+class TemplateEngine(tenjin.Engine):
+    def include(self, template_name, **kwargs):
+        """
+        Tenjin has an issue with nested includes that use the same local variable
+        names, because it uses the same context dict for each level of nesting.
+        The fix is to copy the context.
+        """
+        frame = sys._getframe(1)
+        locals  = frame.f_locals
+        globals = frame.f_globals
+        context = locals["_context"].copy()
+        context.update(kwargs)
+        template = self.get_template(template_name, context, globals)
+        return template.render(context, globals, _buf=locals["_buf"])
diff --git a/c_gen/match.py b/c_gen/match.py
new file mode 100644
index 0000000..611a80d
--- /dev/null
+++ b/c_gen/match.py
@@ -0,0 +1,558 @@
+# 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.
+
+# @brief Match data representation
+#
+# @fixme This still has lots of C specific code that should be moved into c_gen
+
+import sys
+import c_gen.of_g_legacy as of_g
+from generic_utils import *
+import c_gen.loxi_utils_legacy as loxi_utils
+
+#
+# Use 1.2 match semantics for common case
+#
+# Generate maps between generic match and version specific matches
+# Generate dump functions for generic match
+# Generate dump functions for version specific matches
+
+## @var of_match_members
+# The dictionary from unified match members to type and indexing info
+#
+# Keys:
+#   name The unified name used for the member
+#   m_type The data type used for the object in unified structure
+#   print_type The id to use when printing
+#   conditions The condition underwhich the field could occur TBD
+#   takes_mask_in_spec Shown as taking mask in OF 1.2 spec; IGNORED NOW
+#   order Used to define an order for readability
+#   v1_wc_shift The WC shift in OF 1.0
+#   v2_wc_shift The WC shift in OF 1.1
+#
+# Unless noted otherwise, class is 0x8000, OFPXMC_OPENFLOW_BASIC
+# We use the 1.2 names and alias older names
+# Conditions:
+#  is_ipv4(_m):  ((_m)->eth_type == 0x0800)
+#  is_ipv6(_m):  ((_m)->eth_type == 0x86dd)
+#  is_ip(_m):    (is_ipv4(_m) || is_ipv6(_m))
+#  is_arp(_m):   ((_m)->eth_type == 0x0806)
+#  is_tcp(_m):   (is_ip(_m) && ((_m)->ip_proto == 6))
+#  is_udp(_m):   (is_ip(_m) && ((_m)->ip_proto == 17))
+#  is_sctp(_m):  (is_ip(_m) && ((_m)->ip_proto == 132))
+#  is_icmpv4(_m):  (is_ipv4(_m) && ((_m)->ip_proto == 1))
+#  is_icmpv6(_m):  (is_ipv6(_m) && ((_m)->ip_proto == 58))
+#
+
+of_match_members = dict(
+    in_port = dict(
+        name="in_port",
+        m_type="of_port_no_t",
+        print_type="PRIx32",
+        conditions="",
+        v1_wc_shift=0,
+        v2_wc_shift=0,
+        takes_mask_in_spec=False,
+        order=100,
+        ),
+    in_phy_port = dict(
+        name="in_phy_port",
+        m_type="of_port_no_t",
+        print_type="PRIx32",
+        conditions="", # OXM_OF_IN_PORT must be present
+        takes_mask_in_spec=False,
+        order=101,
+        ),
+    metadata = dict(
+        name="metadata",
+        m_type="uint64_t",
+        print_type="PRIx64",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=102,
+        ),
+
+    eth_dst = dict(
+        name="eth_dst",
+        m_type="of_mac_addr_t",
+        v1_wc_shift=3,
+        print_type="\"p\"",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=200,
+        ),
+    eth_src = dict(
+        name="eth_src",
+        m_type="of_mac_addr_t",
+        v1_wc_shift=2,
+        print_type="\"p\"",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=201,
+        ),
+    eth_type = dict(
+        name="eth_type",
+        m_type="uint16_t",
+        v1_wc_shift=4,
+        v2_wc_shift=3,
+        print_type="PRIx16",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=203,
+        ),
+    vlan_vid = dict(  # FIXME: Semantics changed in 1.2
+        # Use CFI bit to indicate tag presence
+        name="vlan_vid",
+        m_type="uint16_t",
+        v1_wc_shift=1,
+        v2_wc_shift=1,
+        print_type="PRIx16",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=210,
+        ),
+    vlan_pcp = dict(
+        name="vlan_pcp",
+        m_type="uint8_t",
+        v1_wc_shift=20,
+        v2_wc_shift=2,
+        print_type="PRIx8",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=211,
+        ),
+
+    ip_dscp = dict(
+        name="ip_dscp",
+        m_type="uint8_t",
+        v1_wc_shift=21,
+        v2_wc_shift=4,
+        print_type="PRIx8",
+        conditions="is_ip(match)",
+        takes_mask_in_spec=False,
+        order=310,
+        ),
+    ip_ecn = dict(
+        name="ip_ecn",
+        m_type="uint8_t",
+        print_type="PRIx8",
+        conditions="is_ip(match)",
+        takes_mask_in_spec=False,
+        order=311,
+        ),
+    ip_proto = dict(
+        name="ip_proto",
+        m_type="uint8_t",
+        v1_wc_shift=5,
+        v2_wc_shift=5,
+        print_type="PRIx8",
+        conditions="is_ip(match)",
+        takes_mask_in_spec=False,
+        order=320,
+        ),
+    ipv4_src = dict(
+        name="ipv4_src",
+        m_type="of_ipv4_t",
+        v1_wc_shift=8,
+        print_type="PRIx32",
+        conditions="is_ipv4(match)",
+        takes_mask_in_spec=True,
+        order=330,
+        ),
+    ipv4_dst = dict(
+        name="ipv4_dst",
+        m_type="of_ipv4_t",
+        v1_wc_shift=14,
+        print_type="PRIx32",
+        conditions="is_ipv4(match)",
+        takes_mask_in_spec=True,
+        order=331,
+        ),
+
+    tcp_dst = dict(
+        name="tcp_dst",
+        m_type="uint16_t",
+        v1_wc_shift=7,
+        v2_wc_shift=7,
+        print_type="PRIx16",
+        conditions="is_tcp(match)",
+        takes_mask_in_spec=False,
+        order=400,
+        ),
+    tcp_src = dict(
+        name="tcp_src",
+        m_type="uint16_t",
+        v1_wc_shift=6,
+        v2_wc_shift=6,
+        print_type="PRIx16",
+        conditions="is_tcp(match)",
+        takes_mask_in_spec=False,
+        order=401,
+        ),
+
+    udp_dst = dict(
+        name="udp_dst",
+        m_type="uint16_t",
+        print_type="PRIx16",
+        conditions="is_udp(match)",
+        takes_mask_in_spec=False,
+        order=410,
+        ),
+    udp_src = dict(
+        name="udp_src",
+        m_type="uint16_t",
+        print_type="PRIx16",
+        conditions="is_udp(match)",
+        takes_mask_in_spec=False,
+        order=411,
+        ),
+
+    sctp_dst = dict(
+        name="sctp_dst",
+        m_type="uint16_t",
+        print_type="PRIx16",
+        conditions="is_sctp(match)",
+        takes_mask_in_spec=False,
+        order=420,
+        ),
+    sctp_src = dict(
+        name="sctp_src",
+        m_type="uint16_t",
+        print_type="PRIx16",
+        conditions="is_sctp(match)",
+        takes_mask_in_spec=False,
+        order=421,
+        ),
+
+    icmpv4_type = dict(
+        name="icmpv4_type",
+        m_type="uint8_t",
+        print_type="PRIx8",
+        conditions="is_icmp_v4(match)",
+        takes_mask_in_spec=False,
+        order=430,
+        ),
+    icmpv4_code = dict(
+        name="icmpv4_code",
+        m_type="uint8_t",
+        print_type="PRIx8",
+        conditions="is_icmp_v4(match)",
+        takes_mask_in_spec=False,
+        order=431,
+        ),
+
+    arp_op = dict(
+        name="arp_op",
+        m_type="uint16_t",
+        print_type="PRIx16",
+        conditions="is_arp(match)",
+        takes_mask_in_spec=False,
+        order=450,
+        ),
+
+    arp_spa = dict(
+        name="arp_spa",
+        m_type="uint32_t",
+        print_type="PRIx32",
+        conditions="is_arp(match)",
+        takes_mask_in_spec=True,
+        order=451,
+        ),
+    arp_tpa = dict(
+        name="arp_tpa",
+        m_type="uint32_t",
+        print_type="PRIx32",
+        conditions="is_arp(match)",
+        takes_mask_in_spec=True,
+        order=452,
+        ),
+
+    arp_sha = dict(
+        name="arp_sha",
+        m_type="of_mac_addr_t",
+        print_type="\"p\"",
+        conditions="is_arp(match)",
+        takes_mask_in_spec=False,
+        order=453,
+        ),
+    arp_tha = dict(
+        name="arp_tha",
+        m_type="of_mac_addr_t",
+        print_type="\"p\"",
+        conditions="is_arp(match)",
+        takes_mask_in_spec=False,
+        order=454,
+        ),
+
+    ipv6_src = dict(
+        name="ipv6_src",
+        m_type="of_ipv6_t",
+        print_type="\"p\"",
+        conditions="is_ipv6(match)",
+        takes_mask_in_spec=True,
+        order=500,
+        ),
+    ipv6_dst = dict(
+        name="ipv6_dst",
+        m_type="of_ipv6_t",
+        print_type="\"p\"",
+        conditions="is_ipv6(match)",
+        takes_mask_in_spec=True,
+        order=501,
+        ),
+
+    ipv6_flabel = dict(
+        name="ipv6_flabel",
+        m_type="uint32_t",
+        print_type="PRIx32",
+        conditions="is_ipv6(match)",
+        takes_mask_in_spec=False, # Comment in openflow.h says True
+        order=502,
+        ),
+
+    icmpv6_type = dict(
+        name="icmpv6_type",
+        m_type="uint8_t",
+        print_type="PRIx8",
+        conditions="is_icmp_v6(match)",
+        takes_mask_in_spec=False,
+        order=510,
+        ),
+    icmpv6_code = dict(
+        name="icmpv6_code",
+        m_type="uint8_t",
+        print_type="PRIx8",
+        conditions="is_icmp_v6(match)",
+        takes_mask_in_spec=False,
+        order=511,
+        ),
+
+    ipv6_nd_target = dict(
+        name="ipv6_nd_target",
+        m_type="of_ipv6_t",
+        print_type="\"p\"",
+        conditions="", # fixme
+        takes_mask_in_spec=False,
+        order=512,
+        ),
+
+    ipv6_nd_sll = dict(
+        name="ipv6_nd_sll",
+        m_type="of_mac_addr_t",
+        print_type="\"p\"",
+        conditions="", # fixme
+        takes_mask_in_spec=False,
+        order=520,
+        ),
+    ipv6_nd_tll = dict(
+        name="ipv6_nd_tll",
+        m_type="of_mac_addr_t",
+        print_type="\"p\"",
+        conditions="", # fixme
+        takes_mask_in_spec=False,
+        order=521,
+        ),
+
+    mpls_label = dict(
+        name="mpls_label",
+        m_type="uint32_t",
+        v2_wc_shift=8,
+        print_type="PRIx32",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=600,
+        ),
+    mpls_tc = dict(
+        name="mpls_tc",
+        m_type="uint8_t",
+        v2_wc_shift=9,
+        print_type="PRIx8",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=601,
+        ),
+
+    bsn_in_ports_128 = dict(
+        name="bsn_in_ports_128",
+        m_type="of_bitmap_128_t",
+        v2_wc_shift=9,
+        print_type="p",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=1000,
+        ),
+
+    bsn_lag_id = dict(
+        name="bsn_lag_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=1001,
+        ),
+
+    bsn_vrf = dict(
+        name="bsn_vrf",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=1002,
+        ),
+
+    bsn_global_vrf_allowed = dict(
+        name="bsn_global_vrf_allowed",
+        m_type="uint8_t",
+        print_type="PRIu8",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=1003,
+        ),
+
+    bsn_l3_interface_class_id = dict(
+        name="bsn_l3_interface_class_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=1003,
+        ),
+
+    bsn_l3_src_class_id = dict(
+        name="bsn_l3_src_class_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=1004,
+        ),
+
+    bsn_l3_dst_class_id = dict(
+        name="bsn_l3_dst_class_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=1005,
+        ),
+)
+
+match_keys_sorted = of_match_members.keys()
+match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
+
+of_v1_keys = [
+    "eth_dst",
+    "eth_src",
+    "eth_type",
+    "in_port",
+    "ipv4_dst",
+    "ip_proto",
+    "ipv4_src",
+    "ip_dscp",
+    "tcp_dst",  # Means UDP too for 1.0 and 1.1
+    "tcp_src",  # Means UDP too for 1.0 and 1.1
+    "vlan_pcp",
+    "vlan_vid"
+    ]
+
+of_v2_keys = [
+    "eth_dst",
+    "eth_src",
+    "eth_type",
+    "in_port",
+    "ipv4_dst",
+    "ip_proto",
+    "ipv4_src",
+    "ip_dscp",
+    "tcp_dst",  # Means UDP too for 1.0 and 1.1
+    "tcp_src",  # Means UDP too for 1.0 and 1.1
+    "vlan_pcp",
+    "vlan_vid",
+    "mpls_label",
+    "mpls_tc",
+    "metadata"
+    ]
+
+of_v2_full_mask = [
+    "eth_dst",
+    "eth_src",
+    "ipv4_dst",
+    "ipv4_src",
+    "metadata"
+    ]
+
+def oxm_index(key):
+    """
+    What's the index called for a match key
+    """
+    return "OF_OXM_INDEX_" + key.upper()
+
+##
+# Check that all members in the hash are recognized as match keys
+def match_sanity_check():
+    count = 0
+    for match_v in ["of_match_v1", "of_match_v2"]:
+        count += 1
+        for mm in of_g.unified[match_v][count]["members"]:
+            key = mm["name"]
+            if key.find("_mask") >= 0:
+                continue
+            if loxi_utils.skip_member_name(key):
+                continue
+            if key == "wildcards":
+                continue
+            if not key in of_match_members:
+                print "Key %s not found in match struct, v %s" % (key, match_v)
+                sys.exit(1)
+
+    # Generate list of OXM names from the unified classes
+    oxm_names = [x[7:] for x in of_g.unified.keys() if
+                 x.startswith('of_oxm_') and
+                 x.find('masked') < 0 and
+                 x.find('header') < 0]
+
+    # Check that all OXMs are in the match members
+    for key in oxm_names:
+        if not key in of_match_members:
+            if not (key.find("_masked") > 0):
+                debug("Key %s in OXM, not of_match_members" % key)
+                sys.exit(1)
+            if not key[:-7] in of_match_members:
+                debug("Key %s in OXM, but %s not in of_match_members"
+                      % (key, key[:-7]))
+                sys.exit(1)
+
+    # Check that all match members are in the OXMs
+    for key in of_match_members:
+        if not key in oxm_names:
+            debug("Key %s in of_match_members, not in OXM" % key)
+            sys.exit(1)
+        oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
+        if of_match_members[key]["m_type"] != oxm_type:
+            debug("Type mismatch for key %s in oxm data: %s vs %s" %
+                  (key, of_match_members[key]["m_type"], oxm_type))
+            sys.exit(1)
diff --git a/c_gen/templates/locitest/test_validator.c b/c_gen/templates/locitest/test_validator.c
index 6b9dd87..eb3cbb6 100644
--- a/c_gen/templates/locitest/test_validator.c
+++ b/c_gen/templates/locitest/test_validator.c
@@ -27,8 +27,8 @@
 ::
 :: include('_copyright.c')
 :: import of_g
-:: from loxi_utils import loxi_utils
-:: from loxi_front_end import type_maps
+:: import c_gen.loxi_utils_legacy as loxi_utils
+:: from c_gen import type_maps
 
 /**
  * Test message validator
diff --git a/c_gen/translation.py b/c_gen/translation.py
new file mode 100644
index 0000000..ef6c11b
--- /dev/null
+++ b/c_gen/translation.py
@@ -0,0 +1,127 @@
+# 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.
+
+##
+# @brief Translation data between openflow.h and LOXI
+#
+
+import re
+import sys
+
+def loxi_name(ident):
+    """
+    Return the LOXI name of an openflow.h identifier
+    """
+
+    # Order at the outer level matters as super strings are listed first
+    rules = [
+# The following are for #define macros and have highest precedence
+        dict(OFP_MAX_TABLE_NAME_LEN = "OF_MAX_TABLE_NAME_LEN"),
+        dict(OFP_MAX_PORT_NAME_LEN = "OF_MAX_PORT_NAME_LEN"),
+        dict(OFP_TCP_PORT = "OF_TCP_PORT"),
+        dict(OFP_SSL_PORT = "OF_SSL_PORT"),
+        dict(OFP_ETH_ALEN = "OF_ETH_ALEN"),
+        dict(OFP_DEFAULT_MISS_SEND_LEN = "OF_DEFAULT_MISS_SEND_LEN"),
+        dict(OFP_VLAN_NONE = "OF_VLAN_UNTAGGED"),
+        dict(OFP_DL_TYPE_ETH2_CUTOFF = "OF_DL_TYPE_ETH2_CUTOFF"),
+        dict(OFP_DL_TYPE_NOT_ETH_TYPE = "OF_DL_TYPE_NOT_ETH_TYPE"),
+        dict(OFP_FLOW_PERMANENT = "OF_FLOW_PERMANENT"),
+        dict(OFP_DEFAULT_PRIORITY = "OF_DEFAULT_PRIORITY"),
+        dict(DESC_STR_LEN = "OF_DESC_STR_LEN"),
+        dict(SERIAL_NUM_LEN = "OF_SERIAL_NUM_LEN"),
+        dict(OFPQ_ALL = "OF_QUEUE_ALL"),
+        dict(OFPQ_MIN_RATE_UNCFG = "OF_QUEUE_MIN_RATE_UNCFG"),
+        dict(OFPQ_MAX_RATE_UNCFG = "OF_QUEUE_MAX_RATE_UNCFG"),
+        dict(OFP_NO_BUFFER = "OF_BUFFER_ID_NO_BUFFER"),
+
+# These are for enums; they map the prefixes
+        dict(OFPP_MAX = "OF_PORT_NUMBER_MAX"), # Special case
+        dict(OFPP_TABLE = "OF_PORT_DEST_USE_TABLE"), # Special case
+        dict(OFPP_ANY = "OF_PORT_DEST_WILDCARD"), # Special case
+        dict(OFPTC_ = "OF_TABLE_CONFIG_"),
+        dict(OFPIEH_ = "OF_IPV6_EXT_HDR_FLAG_"),
+        dict(OFPMBT_ = "OF_METER_BAND_TYPE_"),
+        dict(OFPMC_ = "OF_METER_MOD_COMMAND_"),
+        dict(OFPMF_ = "OF_METER_FLAG_"),
+        dict(OFPTFFC_ = "OF_TABLE_REQUEST_FAILED_"),
+        dict(OFPMMFC_ = "OF_METER_MOD_FAILED_"),
+        dict(OFPPR_ = "OF_PORT_CHANGE_REASON_"),
+        dict(OFPPMFC_ = "OF_PORT_MOD_FAILED_"),
+        dict(OFPP_ = "OF_PORT_DEST_"),
+        dict(OFPRRFC_ = "OF_ROLE_REQUEST_FAILED_"),
+        dict(OFPRR_ = "OF_FLOW_REMOVED_REASON_"),
+        dict(OFPR_ = "OF_PACKET_IN_REASON_"),
+        dict(OFPC_FRAG_ = "OF_CONFIG_FRAG_"),
+        dict(OFPC_INVALID_ = "OF_CONFIG_INVALID_"),
+        dict(OFPCML_ = "OF_CONTROLLER_PKT_"),
+        dict(OFPCR_ROLE_ = "OF_CONTROLLER_ROLE_"),
+        dict(OFPC_ = "OF_CAPABILITIES_FLAG_"),
+        dict(OFPPC_ = "OF_PORT_CONFIG_FLAG_"),
+        dict(OFPPS_ = "OF_PORT_STATE_FLAG_"),
+        dict(OFPPF_ = "OF_PORT_FEATURE_FLAG_"),
+        dict(OFPTT_ = "OF_TABLE_"),
+        dict(OFPT_ = "OF_OBJ_TYPE_"),
+        dict(OFPMT_ = "OF_MATCH_TYPE_"),
+        dict(OFPM_ = "OF_METER_"),
+        dict(OFPXMC_ = "OF_OXM_CLASS_"),
+        dict(OFPVID_ = "OF_VLAN_TAG_"),
+        dict(OFPGC_ = "OF_GROUP_"),
+        dict(OFPGT_ = "OF_GROUP_TYPE_"),
+        dict(OFPG_ = "OF_GROUP_"),
+        dict(OFPET_ = "OF_ERROR_TYPE_"),
+        dict(OFPFC_ = "OF_FLOW_MOD_COMMAND_"),
+        dict(OFPHFC_ = "OF_HELLO_FAILED_"),
+        dict(OFPBRC_ = "OF_REQUEST_FAILED_"),
+        dict(OFPBAC_ = "OF_ACTION_FAILED_"),
+        dict(OFPBIC_ = "OF_INSTRUCTION_FAILED_"),
+        dict(OFPBMC_ = "OF_MATCH_FAILED_"),
+        dict(OFPGMFC_ = "OF_GROUP_MOD_FAILED_"),
+        dict(OFPTMFC_ = "OF_TABLE_MOD_FAILED_"),
+        dict(OFPFMFC_ = "OF_FLOW_MOD_FAILED_"),
+        dict(OFPQOFC_ = "OF_QUEUE_OP_FAILED_"),
+        dict(OFPSCFC_ = "OF_SWITCH_CONFIG_FAILED_"),
+        dict(OFPQCFC_ = "OF_SWITCH_CONFIG_FAILED_"), # See EXT-208
+        dict(OFPAT_ = "OF_ACTION_TYPE_"),
+        dict(OFPFW_ = "OF_FLOW_WC_V1_"),
+        dict(OFPFF_ = "OF_FLOW_MOD_FLAG_"),
+        dict(OFPST_ = "OF_STATS_TYPE_"),
+        dict(OFPSF_ = "OF_STATS_REPLY_FLAG_"),
+        dict(OFPQT_ = "OF_QUEUE_PROPERTY_"),
+        dict(OFPIT_ = "OF_INSTRUCTION_TYPE_"),
+        dict(OFPGFC_ = "OF_GROUP_CAPABILITIES_"),
+        dict(OFPMP_ = "OF_MULTIPART_"),
+        dict(OFPMPF_ = "OF_MULTIPART_FLAG_"),
+        dict(OFPTFPT_ = "OF_TABLE_FEATURE_"),
+        dict(OFPHET = "OF_HELLO_ELEM_TYPE_"),
+        dict(NX_ROLE_ = "OF_NICIRA_CONTROLLER_ROLE_"),
+        ]
+
+    for entry in rules:
+        for id_from, id_to in entry.items():
+            if re.match(id_from, ident):
+                return re.sub(id_from, id_to, ident)
+    return ident
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
new file mode 100644
index 0000000..909ee79
--- /dev/null
+++ b/c_gen/type_maps.py
@@ -0,0 +1,802 @@
+# 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.
+
+#
+# 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
+
+invalid_type = "invalid_type"
+invalid_value = "0xeeee"  # Note, as a string
+
+################################################################
+#
+# 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()
+    }
+
+# HACK shared between actions and action_ids
+of_1_3_action_types = 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:of_1_3_action_types
+    }
+
+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:of_1_3_action_types
+    }
+
+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 = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(
+        q_in_q      = 0,
+        ),
+    # version 1.1
+    of_g.VERSION_1_1:dict(
+        q_in_q      = 0,
+        ),
+    # version 1.2
+    of_g.VERSION_1_2:dict(
+        q_in_q      = 0,
+        ),
+    # version 1.3
+    of_g.VERSION_1_3:dict(
+        q_in_q      = 0,
+        )
+    }
+
+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(),
+    }
+
+# All inheritance data for non-messages
+inheritance_data = dict(
+    of_instruction = instruction_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
+    )
+
+def class_is_virtual(cls):
+    """
+    Returns True if cls is a virtual class
+    """
+    if cls in inheritance_map:
+        return True
+    if cls.find("header") > 0:
+        return True
+    if loxi_utils.class_is_list(cls):
+        return True
+    # TODO get this from the input file when we have virtual class syntax
+    if cls in ["of_flow_mod", "of_stats_request", "of_stats_reply", "of_error_msg", "of_bsn_header", "of_nicira_header", "of_action_bsn", "of_action_nicira", "of_action_id_bsn", "of_action_id_nicira"]:
+        return True
+    return False
+
+################################################################
+#
+# 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,
+        stats_request           = 18,
+        stats_reply             = 19,
+        ),
+
+    # version 1.2
+    of_g.VERSION_1_2:dict(
+        error_msg               = 1,
+        experimenter            = 4,
+        flow_mod                = 14,
+        stats_request           = 18,
+        stats_reply             = 19,
+        ),
+
+    # version 1.3
+    of_g.VERSION_1_3:dict(
+        error_msg               = 1,
+        experimenter            = 4,
+        flow_mod                = 14,
+        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
+        )
+    }
+
+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
+        )
+    }
+
+##
+# These are the objects whose length is specified by an external
+# reference, specifically another data member in the class.
+#
+#external_length_spec = {
+#    ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
+#    ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
+#    ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
+#    ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
+#}
+
+
+################################################################
+#
+# 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 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, 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
+
+# FIXME:  Need to move update for multipart messages
+
+stats_reply_list = [
+    "of_aggregate_stats_reply",
+    "of_desc_stats_reply",
+    "of_experimenter_stats_reply",
+    "of_flow_stats_reply",
+    "of_group_stats_reply",
+    "of_group_desc_stats_reply",
+    "of_group_features_stats_reply",
+    "of_meter_stats_reply",
+    "of_meter_config_stats_reply",
+    "of_meter_features_stats_reply",
+    "of_port_stats_reply",
+    "of_port_desc_stats_reply",
+    "of_queue_stats_reply",
+    "of_table_stats_reply",
+    "of_table_features_stats_reply"
+]
+
+stats_request_list = [
+    "of_aggregate_stats_request",
+    "of_desc_stats_request",
+    "of_experimenter_stats_request",
+    "of_flow_stats_request",
+    "of_group_stats_request",
+    "of_group_desc_stats_request",
+    "of_group_features_stats_request",
+    "of_meter_stats_request",
+    "of_meter_config_stats_request",
+    "of_meter_features_stats_request",
+    "of_port_stats_request",
+    "of_port_desc_stats_request",
+    "of_queue_stats_request",
+    "of_table_stats_request",
+    "of_table_features_stats_request"
+]
+
+flow_mod_list = [
+    "of_flow_add",
+    "of_flow_modify",
+    "of_flow_modify_strict",
+    "of_flow_delete",
+    "of_flow_delete_strict"
+]
+
+error_msg_list = [
+    "of_hello_failed_error_msg",
+    "of_bad_request_error_msg",
+    "of_bad_action_error_msg",
+    "of_bad_instruction_error_msg",
+    "of_bad_match_error_msg",
+    "of_flow_mod_failed_error_msg",
+    "of_group_mod_failed_error_msg",
+    "of_port_mod_failed_error_msg",
+    "of_table_mod_failed_error_msg",
+    "of_queue_op_failed_error_msg",
+    "of_switch_config_failed_error_msg",
+    "of_role_request_failed_error_msg",
+    "of_meter_mod_failed_error_msg",
+    "of_table_features_failed_error_msg",
+    "of_experimenter_error_msg"
+]
+
+def sub_class_map(base_type, version):
+    """
+    Returns an iterable object giving the instance nameys and subclass types
+    for the base_type, version values
+    """
+    rv = []
+    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)
+        if not loxi_utils.class_in_version(subcls, version):
+            continue
+        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 = {}
+
+# Set to empty dict if no extension instructions defined
+extension_queue_prop_subtype = {}
+
+# Set to empty dict if no extension instructions defined
+extension_table_feature_prop_subtype = {}
+
+extension_objects = [
+    extension_message_subtype,
+    extension_action_subtype,
+    extension_action_id_subtype,
+    extension_instruction_subtype,
+    extension_queue_prop_subtype,
+    extension_table_feature_prop_subtype
+]
+
+################################################################
+# These are extension type generic (for messages, actions...)
+################################################################
+
+def extension_to_experimenter_name(cls):
+    """
+    Return the name of the experimenter if class is an
+    extension, else None
+
+    This is brute force; we search all extension data for a match
+    """
+
+    for ext_obj in extension_objects:
+        for version, exp_list in ext_obj.items():
+            for exp_name, classes in exp_list.items():
+                if cls in classes:
+                    return exp_name
+    return None
+
+def extension_to_experimenter_id(cls):
+    """
+    Return the ID of the experimenter if class is an
+    extension, else None
+    """
+    exp_name = extension_to_experimenter_name(cls)
+    if exp_name:
+        return of_g.experimenter_name_to_id[exp_name]
+    return None
+
+def extension_to_experimenter_macro_name(cls):
+    """
+    Return the "macro name" of the ID of the experimenter if class is an
+    extension, else None
+    """
+    exp_name = extension_to_experimenter_name(cls)
+    if exp_name:
+        return "OF_EXPERIMENTER_ID_" + exp_name.upper()
+    return None
+
+def extension_to_subtype(cls, version):
+    """
+    Generic across all extension objects, return subtype identifier
+    """
+    for ext_obj in extension_objects:
+        for version, exp_list in ext_obj.items():
+            for exp_name, classes in exp_list.items():
+                if cls in classes:
+                    return classes[cls]
+
+def class_is_extension(cls, version):
+    """
+    Return True if class, version is recognized as an extension
+    of any type (message, action....)
+
+    Accepts of_g.OF_VERSION_ANY
+    """
+
+    for ext_obj in extension_objects:
+        if cls_is_ext_obj(cls, version, ext_obj):
+            return True
+
+    return False
+
+# Internal
+def cls_is_ext_obj(cls, version, ext_obj):
+    """
+    @brief Return True if cls in an extension of type ext_obj
+    @param cls The class to check
+    @param version The version to check
+    @param ext_obj The extension object dictionary (messages, actions...)
+
+    Accepts of_g.VERSION_ANY
+    """
+
+    # Call with each version if "any" is passed
+    if version == of_g.VERSION_ANY:
+        for v in of_g.of_version_range:
+            if cls_is_ext_obj(cls, v, ext_obj):
+                return True
+    else:   # Version specified
+        if version in ext_obj:
+            for exp, subtype_vals in ext_obj[version].items():
+                if cls in subtype_vals:
+                    return True
+
+    return False
+
+################################################################
+# These are extension message specific
+################################################################
+
+def message_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an  extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_message_subtype)
+
+def extension_message_to_subtype(cls, version):
+    """
+    Return the subtype of the experimenter message if the class is an
+    extension, else None
+    """
+    if version in extension_message_subtype:
+        for exp, classes in extension_message_subtype[version].items():
+            for ext_class, subtype in classes.items():
+                if cls == ext_class:
+                    return subtype
+    return None
+
+################################################################
+# These are extension action specific
+################################################################
+
+def action_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an action extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_action_subtype)
+
+def extension_action_to_subtype(cls, version):
+    """
+    Return the ID of the action subtype (for its experimenteer)
+    if class is an action extension, else None
+    """
+    if version in extension_action_subtype:
+        for exp, classes in extension_action_subtype[version].items():
+            if cls in classes:
+                return classes[cls]
+
+    return None
+
+################################################################
+# These are extension action specific
+################################################################
+
+def action_id_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an action ID extension
+    This is brute force, searching records for a match
+    """
+    if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
+        return False
+    return cls_is_ext_obj(cls, version, extension_action_id_subtype)
+
+def extension_action_id_to_subtype(cls, version):
+    """
+    Return the ID of the action ID subtype (for its experimenteer)
+    if class is an action ID extension, else None
+    """
+    if version in extension_action_id_subtype:
+        for exp, classes in extension_action_id_subtype[version].items():
+            if cls in classes:
+                return classes[cls]
+
+    return None
+
+################################################################
+# These are extension instruction specific
+################################################################
+
+def instruction_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an instruction extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_instruction_subtype)
+
+################################################################
+# These are extension queue_prop specific
+################################################################
+
+def queue_prop_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an instruction extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
+
+################################################################
+# These are extension table_feature_prop specific
+################################################################
+
+def table_feature_prop_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an instruction extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version,
+                          extension_table_feature_prop_subtype)