Fix issues with C backend with new error message hierarchy
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index a0fec7e..c5d69d0 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -67,6 +67,10 @@
                 out.write("    %d%s /* %s */\n" %
                           (type_maps.type_val[("of_stats_request", version)],
                            comma, cls))
+            elif cls in type_maps.error_msg_list:
+                out.write("    %d%s /* %s */\n" %
+                          (type_maps.type_val[("of_error_msg", version)],
+                           comma, cls))
             elif cls in type_maps.flow_mod_list:
                 out.write("    %d%s /* %s */\n" %
                           (type_maps.type_val[("of_flow_mod", version)],
@@ -230,6 +234,9 @@
     out.write("#include <loci/loci.h>\n\n")
 
     # Generate maps from wire type values to object IDs
+    gen_type_to_object_id(out, "error_msg_type_to_id", "OF_ERROR_MSG",
+                          "OF_%s_ERROR_MSG", type_maps.error_types,
+                          max_type_value)
     gen_type_to_object_id(out, "action_type_to_id", "OF_ACTION",
                           "OF_ACTION_%s", type_maps.action_types,
                           max_type_value)
@@ -384,6 +391,42 @@
     return of_%(name)s_type_to_id[version][%(name)s];
 }
 """
+
+    error_msg_template = """
+/**
+ * %(name)s wire type to object ID array.
+ * Treat as private; use function accessor below
+ */
+
+extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
+
+#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
+
+/**
+ * Map an %(name)s wire value to an OF object
+ * @param %(name)s The %(name)s type wire value
+ * @param version The version associated with the check
+ * @return The %(name)s OF object type
+ * @return OF_OBJECT_INVALID if type does not map to an object
+ *
+ */
+static inline of_object_id_t
+of_error_msg_to_object_id(uint16_t %(name)s, of_version_t version)
+{
+    if (!OF_VERSION_OKAY(version)) {
+        return OF_OBJECT_INVALID;
+    }
+    if (%(name)s == OF_EXPERIMENTER_TYPE) {
+        return OF_EXPERIMENTER_ERROR_MSG;
+    }
+    if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
+        return OF_OBJECT_INVALID;
+    }
+
+    return of_%(name)s_type_to_id[version][%(name)s];
+}
+"""
+
     # Experimenter mapping functions
     # Currently we support very few candidates, so we just do a
     # list of if/elses
@@ -457,6 +500,7 @@
     of_version_t ver;
     of_object_id_t obj_id;
     uint16_t stats_type;
+    uint16_t err_type;
     uint8_t flow_mod_cmd;
 
     if (length < OF_MESSAGE_MIN_LENGTH) {
@@ -503,6 +547,14 @@
         }
     }
 
+    if (obj_id == OF_ERROR_MSG) {
+        if (length < OF_MESSAGE_MIN_ERROR_LENGTH) {
+            return OF_OBJECT_INVALID;
+        }
+        err_type = of_message_error_type_get(msg);
+        obj_id = of_error_msg_to_object_id(err_type, ver);
+    }
+
     return obj_id;
 }
 """
@@ -557,6 +609,12 @@
               dict(name="stats_request", u_name="STATS_REQUEST",
                    ar_len=ar_len))
 
+    ar_len = type_maps.type_array_len(type_maps.error_types,
+                                      max_type_value)
+    out.write(error_msg_template %
+              dict(name="error_msg", u_name="ERROR_MSG", ar_len=ar_len))
+#     out.write(error_msg_function)
+
     ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
     out.write(map_template %
               dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))
@@ -725,6 +783,46 @@
 """)
 
     ################################################################
+    # Generate object ID to the error sub-type map
+    ################################################################
+    out.write("""
+/**
+ * Map an object ID to an error type
+ * @param id An object ID
+ * @return The wire value for the error type
+ * @return -1 if not supported for this version
+ * @return -1 if id is not a specific error type ID
+ *
+ * Note that the value is returned as a signed integer.  So -1 is
+ * an error code, while 0xffff is the usual "experimenter" code.
+ */
+
+static inline int
+of_object_to_error_type(of_object_id_t id, of_version_t version)
+{
+    if (!OF_VERSION_OKAY(version)) {
+        return -1;
+    }
+    switch (id) {""")
+    error_names = set()
+    for ver in of_g.of_version_range:
+        for name in type_maps.error_types[ver]:
+            error_names.add(name)
+    for name in error_names:
+        out.write("""
+    case OF_%(name)s_ERROR_MSG:
+        if (OF_ERROR_TYPE_%(name)s_SUPPORTED(version))
+            return OF_ERROR_TYPE_%(name)s_BY_VERSION(version);
+        break;""" % {"name": name.upper()})
+    out.write("""
+    default:
+        break;
+    }
+    return -1; /* Not recognized as error type object for this version */
+}
+""")
+
+    ################################################################
     # Generate object ID to the flow mod sub-type map
     ################################################################
 
@@ -890,6 +988,10 @@
         /* It's a stats obj */
         of_message_stats_type_set(msg, type);
     }
+    if ((type = of_object_to_error_type(id, ver)) >= 0) {
+        /* It's a stats obj */
+        of_message_error_type_set(msg, type);
+    }
     if ((type = of_object_to_flow_mod_command(id, ver)) >= 0) {
         /* It's a flow mod obj */
         of_message_flow_mod_command_set(msg, ver, type);
diff --git a/c_gen/templates/of_message.h b/c_gen/templates/of_message.h
index 944f6d2..165fe51 100644
--- a/c_gen/templates/of_message.h
+++ b/c_gen/templates/of_message.h
@@ -45,11 +45,13 @@
 #define OF_MESSAGE_LENGTH_OFFSET 2
 #define OF_MESSAGE_XID_OFFSET 4
 #define OF_MESSAGE_HEADER_LENGTH 8
+#define OF_MESSAGE_ERROR_TYPE_OFFSET 8
 #define OF_MESSAGE_STATS_TYPE_OFFSET 8
 #define OF_MESSAGE_FLOW_MOD_COMMAND_OFFSET(version) ((version) == 1 ? 56 : 25)
 
 #define OF_MESSAGE_MIN_LENGTH 8
 #define OF_MESSAGE_MIN_STATS_LENGTH (OF_MESSAGE_STATS_TYPE_OFFSET + 2)
+#define OF_MESSAGE_MIN_ERROR_LENGTH (OF_MESSAGE_ERROR_TYPE_OFFSET + 4)
 #define OF_MESSAGE_MIN_FLOW_MOD_LENGTH(version)  ((version) == 1 ? 57 : 26)
 
 #define OF_MESSAGE_EXPERIMENTER_ID_OFFSET 8
@@ -177,6 +179,25 @@
     buf_u16_set(msg + OF_MESSAGE_STATS_TYPE_OFFSET, type);
 }
 
+/**
+ * @brief Get/set error type of a message
+ * @param msg Pointer to the message buffer of sufficient length
+ * @param type Data for set operation
+ * @returns get returns error type in host order
+ */
+
+static inline uint16_t
+of_message_error_type_get(of_message_t msg) {
+    uint16_t val;
+    buf_u16_get(msg + OF_MESSAGE_ERROR_TYPE_OFFSET, &val);
+    return val;
+}
+
+static inline void
+of_message_error_type_set(of_message_t msg, uint16_t type) {
+    buf_u16_set(msg + OF_MESSAGE_ERROR_TYPE_OFFSET, type);
+}
+
 
 /**
  * @brief Get/set experimenter ID of a message
diff --git a/loxi_front_end/type_maps.py b/loxi_front_end/type_maps.py
index b64f1b5..a3394b2 100644
--- a/loxi_front_end/type_maps.py
+++ b/loxi_front_end/type_maps.py
@@ -155,7 +155,7 @@
     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_bsn_header", "of_nicira_header", "of_action_bsn", "of_action_nicira", "of_action_id_bsn", "of_action_id_nicira"]:
+    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
 
@@ -169,6 +169,7 @@
 message_types = {
     # version 1.0
     of_g.VERSION_1_0:dict(
+        error_msg               = 1,
         experimenter            = 4,
         flow_mod                = 14,
         stats_request           = 16,
@@ -177,6 +178,7 @@
 
     # version 1.1
     of_g.VERSION_1_1:dict(
+        error_msg               = 1,
         experimenter            = 4,
         flow_mod                = 14,
         stats_request           = 18,
@@ -185,6 +187,7 @@
 
     # version 1.2
     of_g.VERSION_1_2:dict(
+        error_msg               = 1,
         experimenter            = 4,
         flow_mod                = 14,
         stats_request           = 18,
@@ -193,6 +196,7 @@
 
     # version 1.3
     of_g.VERSION_1_3:dict(
+        error_msg               = 1,
         experimenter            = 4,
         flow_mod                = 14,
         stats_request           = 18,  # FIXME Multipart
@@ -476,6 +480,24 @@
     "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
diff --git a/of_g.py b/of_g.py
index 651ee64..d63689f 100644
--- a/of_g.py
+++ b/of_g.py
@@ -174,7 +174,7 @@
 
 ## These members do not get normal accessors
 
-skip_members = ["version", "type", "length", "stats_type", "len",
+skip_members = ["version", "type", "length", "err_type", "stats_type", "len",
                 "type_len", "actions_len", "_command"]
 
 ## Some OpenFlow string length constants
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 026fa60..de63eb8 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -175,7 +175,7 @@
     OFPAT_SET_TP_SRC = 9,
     OFPAT_SET_TP_DST = 10,
     OFPAT_ENQUEUE = 11,
-    OFPAT_VENDOR = 0xffff,
+    OFPAT_EXPERIMENTER = 0xffff,
 };
 
 enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
@@ -221,7 +221,7 @@
     OFPST_TABLE = 3,
     OFPST_PORT = 4,
     OFPST_QUEUE = 5,
-    OFPST_VENDOR = 0xffff,
+    OFPST_EXPERIMENTER = 0xffff,
 };
 
 enum ofp_packet_in_reason(wire_type=uint8_t) {
@@ -259,7 +259,7 @@
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
-    OFPBRC_BAD_VENDOR = 3,
+    OFPBRC_BAD_EXPERIMENTER = 3,
     OFPBRC_BAD_SUBTYPE = 4,
     OFPBRC_EPERM = 5,
     OFPBRC_BAD_LEN = 6,
@@ -270,8 +270,8 @@
 enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
-    OFPBAC_BAD_VENDOR = 2,
-    OFPBAC_BAD_VENDOR_TYPE = 3,
+    OFPBAC_BAD_EXPERIMENTER = 2,
+    OFPBAC_BAD_EXPERIMENTER_TYPE = 3,
     OFPBAC_BAD_OUT_PORT = 4,
     OFPBAC_BAD_ARGUMENT = 5,
     OFPBAC_EPERM = 6,
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 589d7bf..4408249 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -292,7 +292,7 @@
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
     OFPBRC_BAD_EXPERIMENTER = 3,
-    OFPBRC_BAD_EXP_TYPE = 4,
+    OFPBRC_BAD_EXPERIMENTER_TYPE = 4,
     OFPBRC_EPERM = 5,
     OFPBRC_BAD_LEN = 6,
     OFPBRC_BUFFER_EMPTY = 7,
@@ -307,7 +307,7 @@
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
-    OFPBAC_BAD_EXP_TYPE = 3,
+    OFPBAC_BAD_EXPERIMENTER_TYPE = 3,
     OFPBAC_BAD_OUT_PORT = 4,
     OFPBAC_BAD_ARGUMENT = 5,
     OFPBAC_EPERM = 6,
@@ -329,7 +329,7 @@
     OFPBIC_UNSUP_METADATA = 3,
     OFPBIC_UNSUP_METADATA_MASK = 4,
     OFPBIC_BAD_EXPERIMENTER = 5,
-    OFPBIC_BAD_EXP_TYPE = 6,
+    OFPBIC_BAD_EXPERIMENTER_TYPE = 6,
     OFPBIC_BAD_LEN = 7,
     OFPBIC_EPERM = 8,
 };
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index 97adfd4..d08568a 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -338,7 +338,7 @@
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
     OFPBRC_BAD_EXPERIMENTER = 3,
-    OFPBRC_BAD_EXP_TYPE = 4,
+    OFPBRC_BAD_EXPERIMENTER_TYPE = 4,
     OFPBRC_EPERM = 5,
     OFPBRC_BAD_LEN = 6,
     OFPBRC_BUFFER_EMPTY = 7,
@@ -354,7 +354,7 @@
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
-    OFPBAC_BAD_EXP_TYPE = 3,
+    OFPBAC_BAD_EXPERIMENTER_TYPE = 3,
     OFPBAC_BAD_OUT_PORT = 4,
     OFPBAC_BAD_ARGUMENT = 5,
     OFPBAC_EPERM = 6,
@@ -376,7 +376,7 @@
     OFPBIC_UNSUP_METADATA = 3,
     OFPBIC_UNSUP_METADATA_MASK = 4,
     OFPBIC_BAD_EXPERIMENTER = 5,
-    OFPBIC_BAD_EXP_TYPE = 6,
+    OFPBIC_BAD_EXPERIMENTER_TYPE = 6,
     OFPBIC_BAD_LEN = 7,
     OFPBIC_EPERM = 8,
 };
diff --git a/py_gen/templates/action.py b/py_gen/templates/action.py
index fba5294..fcfd9a5 100644
--- a/py_gen/templates/action.py
+++ b/py_gen/templates/action.py
@@ -57,12 +57,7 @@
 
 :: #endfor
 
-:: if version == of_g.VERSION_1_0:
-def parse_vendor(reader):
-:: else:
 def parse_experimenter(reader):
-:: #endif
-
     experimenter, = reader.peek("!4xL")
     if experimenter == 0x005c16c7: # Big Switch Networks
         subtype, = reader.peek("!8xL")