Merge into master from pull request #213:
Adding unpadded Instruction Ids for ofp_table_features_prop_instructions* (https://github.com/floodlight/loxigen/pull/213)
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index cbbcfba..688578e 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -437,6 +437,7 @@
 of_object_id_t of_action_to_object_id(int action, of_version_t version);
 of_object_id_t of_action_id_to_object_id(int action_id, of_version_t version);
 of_object_id_t of_instruction_to_object_id(int instruction, of_version_t version);
+of_object_id_t of_instruction_id_to_object_id(int instruction, of_version_t version);
 of_object_id_t of_queue_prop_to_object_id(int queue_prop, of_version_t version);
 of_object_id_t of_table_feature_prop_to_object_id(int table_feature_prop, of_version_t version);
 of_object_id_t of_meter_band_to_object_id(int meter_band, of_version_t version);
@@ -2371,6 +2372,10 @@
                 out.write("""
     obj->wire_type_get = of_instruction_wire_object_id_get;
 """)
+            if loxi_utils.class_is_instruction_id(cls):
+                out.write("""
+    obj->wire_type_get = of_instruction_id_wire_object_id_get;
+""")
             if loxi_utils.class_is_queue_prop(cls):
                     out.write("""
     obj->wire_type_get = of_queue_prop_wire_object_id_get;
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index ac4a972..a13e23e 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -118,6 +118,9 @@
     gen_type_to_object_id(out, "instruction_type_to_id", "OF_INSTRUCTION",
                           "OF_INSTRUCTION_%s", type_maps.instruction_types,
                           max_type_value)
+    gen_type_to_object_id(out, "instruction_id_type_to_id", "OF_INSTRUCTION_ID",
+                          "OF_INSTRUCTION_ID_%s", type_maps.instruction_id_types,
+                          max_type_value)
     gen_type_to_object_id(out, "queue_prop_type_to_id", "OF_QUEUE_PROP",
                           "OF_QUEUE_PROP_%s", type_maps.queue_prop_types,
                           max_type_value)
@@ -565,6 +568,11 @@
     out.write(map_with_experimenter_template %
               dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))
 
+    # Instruction ID types array gen
+    ar_len = type_maps.type_array_len(type_maps.instruction_id_types, max_type_value)
+    out.write(map_with_experimenter_template %
+              dict(name="instruction_id", u_name="INSTRUCTION_ID", ar_len=ar_len))
+
     # Queue prop types array gen
     ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
                                       max_type_value)
@@ -716,6 +724,8 @@
 extern void of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
 extern void of_instruction_wire_object_id_get(of_object_t *obj,
     of_object_id_t *id);
+extern void of_instruction_id_wire_object_id_get(of_object_t *obj,
+    of_object_id_t *id);
 extern void of_queue_prop_wire_object_id_get(of_object_t *obj,
     of_object_id_t *id);
 extern void of_table_feature_prop_wire_object_id_get(of_object_t *obj,
diff --git a/c_gen/loxi_utils_legacy.py b/c_gen/loxi_utils_legacy.py
index 4092d4f..df93c2b 100644
--- a/c_gen/loxi_utils_legacy.py
+++ b/c_gen/loxi_utils_legacy.py
@@ -191,7 +191,26 @@
 
     # For each vendor, check for vendor specific action
     for exp in of_g.experimenter_name_to_id:
-        if cls.find("of_instruction_" + exp) == 0:
+        if cls.find("of_instruction" + exp) == 0:
+            return True
+
+    return False
+
+def class_is_instruction_id(cls):
+    """
+    Return True if cls_name is an action object
+
+    Note that instruction_id is not an instruction object, though it has
+    the same header.  It looks like an instruction header, but the type
+    is used to identify a kind of instruction, it does not indicate the
+    type of the object following.
+    """
+    if cls.find("of_instruction_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_instruction_id_" + exp) == 0:
             return True
 
     return False
diff --git a/c_gen/templates/of_type_maps.c b/c_gen/templates/of_type_maps.c
index c00694c..ef3f82b 100644
--- a/c_gen/templates/of_type_maps.c
+++ b/c_gen/templates/of_type_maps.c
@@ -313,6 +313,43 @@
     return OF_ERROR_NONE;
 }
 
+
+/**
+ * @fixme to do when we have instruction extensions
+ * See extension_action above
+ */
+
+static int
+extension_instruction_id_object_id_get(of_object_t *obj, of_object_id_t *id)
+{
+    uint32_t exp_id;
+    uint8_t *buf;
+
+    *id = OF_INSTRUCTION_ID_EXPERIMENTER;
+
+    buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
+
+    buf_u32_get(buf + OF_INSTRUCTION_EXPERIMENTER_ID_OFFSET, &exp_id);
+
+    switch (exp_id) {
+    case OF_EXPERIMENTER_ID_BSN: {
+        uint32_t subtype;
+        buf_u32_get(buf + OF_INSTRUCTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
+        switch (subtype) {
+        case 0: *id = OF_INSTRUCTION_ID_BSN_DISABLE_SRC_MAC_CHECK; break;
+        case 1: *id = OF_INSTRUCTION_ID_BSN_ARP_OFFLOAD; break;
+        case 2: *id = OF_INSTRUCTION_ID_BSN_DHCP_OFFLOAD; break;
+        case 3: *id = OF_INSTRUCTION_ID_BSN_DISABLE_SPLIT_HORIZON_CHECK; break;
+        case 4: *id = OF_INSTRUCTION_ID_BSN_PERMIT; break;
+        case 5: *id = OF_INSTRUCTION_ID_BSN_DENY; break;
+        }
+        break;
+    }
+    }
+
+    return OF_ERROR_NONE;
+}
+
 /**
  * Get the object ID based on the wire buffer for an instruction object
  * @param obj The object being referenced
@@ -336,6 +373,29 @@
     LOCI_ASSERT(*id != OF_OBJECT_INVALID);
 }
 
+/**
+ * Get the object ID based on the wire buffer for an instruction ID object
+ * @param obj The object being referenced
+ * @param id Where to store the object ID
+ */
+
+
+void
+of_instruction_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
+{
+    int wire_type;
+
+    of_tlv16_wire_type_get(obj, &wire_type);
+    if (wire_type == OF_EXPERIMENTER_TYPE) {
+        extension_instruction_id_object_id_get(obj, id);
+        return;
+    }
+
+    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_INSTRUCTION_ID_ITEM_COUNT);
+
+    *id = of_instruction_id_type_to_id[obj->version][wire_type];
+    LOCI_ASSERT(*id != OF_OBJECT_INVALID);
+}
 
 /**
  * @fixme to do when we have queue_prop extensions
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
index 875a34e..ee452fc 100644
--- a/c_gen/type_maps.py
+++ b/c_gen/type_maps.py
@@ -584,6 +584,20 @@
 }
 
 # Set to empty dict if no extension instructions defined
+extension_instruction_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(
+        bsn = {   # of_instruction_bsn_
+            },
+        nicira = {   # of_instruction_nicira_
+            }
+        ),
+}
+
+# Set to empty dict if no extension instructions defined
 extension_queue_prop_subtype = {}
 
 # Set to empty dict if no extension instructions defined
@@ -594,6 +608,7 @@
     extension_action_subtype,
     extension_action_id_subtype,
     extension_instruction_subtype,
+    extension_instruction_id_subtype,
     extension_queue_prop_subtype,
     extension_table_feature_prop_subtype
 ]
@@ -768,6 +783,17 @@
     return cls_is_ext_obj(cls, version, extension_instruction_subtype)
 
 ################################################################
+# These are extension instruction specific
+################################################################
+
+def instruction_id_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an instruction ID extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_instruction_id_subtype)
+
+################################################################
 # These are extension queue_prop specific
 ################################################################
 
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index a91c859..6010880 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -877,6 +877,11 @@
     pad(4);
 };
 
+struct of_instruction_id {
+    uint16_t type;
+    uint16_t len;
+};
+
 struct of_instruction {
     uint16_t type == ?;
     uint16_t len;
@@ -1610,13 +1615,13 @@
     uint16_t         type == 0;
     uint16_t         length;
     // FIXME Check if instruction_t is right for ids here
-    list(of_instruction_t)   instruction_ids;
+    list(of_instruction_id_t)   instruction_ids;
 };
 
 struct of_table_feature_prop_instructions_miss : of_table_feature_prop {
     uint16_t         type == 1;
     uint16_t         length;
-    list(of_instruction_t)   instruction_ids;
+    list(of_instruction_id_t)   instruction_ids;
 };
 
 struct of_table_feature_prop_next_tables : of_table_feature_prop {
diff --git a/test_data/of13/instruction_id_goto_table.data b/test_data/of13/instruction_id_goto_table.data
new file mode 100644
index 0000000..e52d9c9
--- /dev/null
+++ b/test_data/of13/instruction_id_goto_table.data
@@ -0,0 +1,8 @@
+-- binary
+00 01 # type
+00 04 # length
+-- python
+ofp.instruction_id.goto_table()
+-- c
+obj = of_instruction_id_goto_table_new(OF_VERSION_1_3);
+-- java