Merge into master from pull request #216:
Generate LOCI wire type parsers from the IR (https://github.com/floodlight/loxigen/pull/216)
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index a13e23e..19d7587 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -711,7 +711,6 @@
 extern void of_object_message_wire_length_set(of_object_t *obj, int bytes);
 
 extern void of_oxm_wire_length_get(of_object_t *obj, int *bytes);
-extern void of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
 
 extern void of_tlv16_wire_length_get(of_object_t *obj, int *bytes);
 extern void of_tlv16_wire_length_set(of_object_t *obj, int bytes);
@@ -720,23 +719,6 @@
 extern void of_u16_len_wire_length_get(of_object_t *obj, int *bytes);
 extern void of_u16_len_wire_length_set(of_object_t *obj, int bytes);
 
-extern void of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
-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,
-    of_object_id_t *id);
-extern void of_meter_band_wire_object_id_get(of_object_t *obj,
-    of_object_id_t *id);
-extern void of_hello_elem_wire_object_id_get(of_object_t *obj,
-    of_object_id_t *id);
-extern void of_bsn_tlv_wire_object_id_get(of_object_t *obj,
-    of_object_id_t *id);
-
 #define OF_OXM_LENGTH_GET(hdr) (((hdr) & 0xff) + 4)
 #define OF_OXM_LENGTH_SET(hdr, val)                         \\
     (hdr) = ((hdr) & 0xffffff00) + (((val) - 4) & 0xff)
@@ -748,7 +730,6 @@
                                                     int *bytes);
 extern void of_meter_stats_wire_length_get(of_object_t *obj, int *bytes);
 extern void of_meter_stats_wire_length_set(of_object_t *obj, int bytes);
-extern int of_extension_object_wire_push(of_object_t *obj);
 
 """)
 
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index 121bc42..6f0f6e9 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -78,6 +78,34 @@
         class_name=uclass.name,
         versioned_type_members=versioned_type_members)
 
+ParseWireTypesData = namedtuple('ParseWireTypesData',
+    ['class_name', 'versioned'])
+ParseWireTypesVersion = namedtuple('ParseWireTypesVersion',
+    ['discriminator', 'subclasses'])
+ParseWireTypesSubclass = namedtuple('ParseWireTypesSubclass',
+    ['class_name', 'value', 'virtual'])
+
+def parse_wire_types_data(uclass):
+    if not uclass.virtual:
+        return None
+
+    discriminator = uclass.discriminator
+
+    # Generate a dict of version -> ParseWireTypesVersion
+    versioned = {}
+    for version, ofclass in sorted(uclass.version_classes.items()):
+        subclasses = [ParseWireTypesSubclass(class_name=subclass.name,
+                                             value=subclass.member_by_name(discriminator.name).value,
+                                             virtual=subclass.virtual)
+                      for subclass in ofclass.protocol.classes if subclass.superclass and subclass.superclass.name == ofclass.name]
+
+        subclasses.sort(key=lambda x: x.value)
+        versioned[version] = ParseWireTypesVersion(discriminator=discriminator,
+                                                   subclasses=subclasses)
+
+    return ParseWireTypesData(class_name=uclass.name,
+                              versioned=sorted(versioned.items()))
+
 # Output multiple LOCI classes into each C file. This reduces the overhead of
 # parsing header files, which takes longer than compiling the actual code
 # for many classes. It also reduces the compiled code size.
@@ -86,7 +114,8 @@
         with template_utils.open_output(install_dir, "loci/src/class%02d.c" % i) as out:
             for uclass in chunk:
                 util.render_template(out, "class.c",
-                    push_wire_types_data=push_wire_types_data(uclass))
+                    push_wire_types_data=push_wire_types_data(uclass),
+                    parse_wire_types_data=parse_wire_types_data(uclass))
                 # Append legacy generated code
                 c_code_gen.gen_new_function_definitions(out, uclass.name)
                 c_code_gen.gen_accessor_definitions(out, uclass.name)
@@ -98,7 +127,8 @@
             continue
         with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
             util.render_template(out, "class.c",
-                push_wire_types_data=None)
+                push_wire_types_data=None,
+                parse_wire_types_data=None)
             # Append legacy generated code
             c_code_gen.gen_new_function_definitions(out, cls)
             c_code_gen.gen_accessor_definitions(out, cls)
@@ -119,7 +149,8 @@
     for cls in of_g.ordered_list_objects:
         with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
             util.render_template(out, "class.c",
-                push_wire_types_data=None)
+                push_wire_types_data=None,
+                parse_wire_types_data=None)
             # Append legacy generated code
             c_code_gen.gen_new_function_definitions(out, cls)
             c_code_gen.gen_list_accessors(out, cls)
diff --git a/c_gen/templates/_parse_wire_types.c b/c_gen/templates/_parse_wire_types.c
new file mode 100644
index 0000000..81878e6
--- /dev/null
+++ b/c_gen/templates/_parse_wire_types.c
@@ -0,0 +1,68 @@
+:: # 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.
+::
+void
+${data.class_name}_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
+{
+    unsigned char *buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
+    switch (obj->version) {
+:: for version, version_data in data.versioned:
+    case ${version.constant_version(prefix='OF_VERSION_')}: {
+:: m = version_data.discriminator
+:: if m.length == 1:
+        uint8_t value = *(uint8_t *)(buf + ${m.offset}); /* ${m.name} */
+:: elif m.length == 2:
+        uint16_t value = U16_NTOH(*(uint16_t *)(buf + ${m.offset})); /* ${m.name} */
+:: elif m.length == 4:
+        uint32_t value = U32_NTOH(*(uint32_t *)(buf + ${m.offset})); /* ${m.name} */
+:: elif m.length == 8:
+        uint64_t value = U64_NTOH(*(uint64_t *)(buf + ${m.offset})); /* ${m.name} */
+:: else:
+:: raise("unsupported parse_wire_types length %d" % m.length)
+:: #endif
+::
+        switch (value) {
+:: for subclass in version_data.subclasses:
+        case ${hex(subclass.value)}:
+:: if subclass.virtual:
+            ${subclass.class_name}_wire_object_id_get(obj, id);
+:: else:
+            *id = ${subclass.class_name.upper()};
+:: #endif
+            break;
+:: #endfor
+        default:
+            *id = ${data.class_name.upper()};
+            break;
+        }
+        break;
+    }
+:: #endfor
+    default:
+        LOCI_ASSERT(0);
+    }
+}
diff --git a/c_gen/templates/class.c b/c_gen/templates/class.c
index 044e03e..815dafa 100644
--- a/c_gen/templates/class.c
+++ b/c_gen/templates/class.c
@@ -35,3 +35,8 @@
 :: include("_push_wire_types.c", data=push_wire_types_data)
 
 :: #endif
+
+:: if parse_wire_types_data:
+:: include("_parse_wire_types.c", data=parse_wire_types_data)
+
+:: #endif
diff --git a/c_gen/templates/loci_classes.h b/c_gen/templates/loci_classes.h
index 3486055..12c07d1 100644
--- a/c_gen/templates/loci_classes.h
+++ b/c_gen/templates/loci_classes.h
@@ -25,11 +25,16 @@
 :: # EPL for the specific language governing permissions and limitations
 :: # under the EPL.
 ::
+:: import loxi_globals
 :: include('_copyright.c')
 ::
 #ifndef __LOCI_CLASSES_H__
 #define __LOCI_CLASSES_H__
 
+:: for uclass in loxi_globals.unified.classes:
+void ${uclass.name}_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
+:: #endfor
+
 ${legacy_code}
 
 #endif
diff --git a/c_gen/templates/locitest/test_utils.c b/c_gen/templates/locitest/test_utils.c
index 563f510..10a6b3d 100644
--- a/c_gen/templates/locitest/test_utils.c
+++ b/c_gen/templates/locitest/test_utils.c
@@ -119,6 +119,29 @@
 }
 
 static int
+test_of_object_new_from_message(void)
+{
+    /* v1 OFPT_HELLO, xid=0x12345678 */
+    uint8_t data[] = { 0x01, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78 };
+    uint8_t *buf = malloc(sizeof(data));
+    memcpy(buf, data, sizeof(data));
+
+    of_object_t *obj = of_object_new_from_message(buf, sizeof(data));
+
+    TEST_ASSERT(obj != NULL);
+    TEST_ASSERT(obj->version == OF_VERSION_1_0);
+    TEST_ASSERT(obj->object_id == OF_HELLO);
+
+    uint32_t xid;
+    of_hello_xid_get(obj, &xid);
+    TEST_ASSERT(xid == 0x12345678);
+
+    of_object_delete(obj);
+
+    return TEST_PASS;
+}
+
+static int
 test_of_object_new_from_message_preallocated(void)
 {
     /* v1 OFPT_HELLO, xid=0x12345678 */
@@ -129,8 +152,8 @@
         &storage, buf, sizeof(buf));
 
     TEST_ASSERT(obj != NULL);
-    TEST_ASSERT(obj->version = OF_VERSION_1_0);
-    TEST_ASSERT(obj->object_id = OF_HELLO);
+    TEST_ASSERT(obj->version == OF_VERSION_1_0);
+    TEST_ASSERT(obj->object_id == OF_HELLO);
 
     uint32_t xid;
     of_hello_xid_get(obj, &xid);
@@ -143,6 +166,7 @@
 run_utility_tests(void)
 {
     RUN_TEST(has_outport);
+    RUN_TEST(of_object_new_from_message);
     RUN_TEST(of_object_new_from_message_preallocated);
     RUN_TEST(dump_objs);
 
diff --git a/c_gen/templates/of_object.c b/c_gen/templates/of_object.c
index 8fd0aab..69bd8d3 100644
--- a/c_gen/templates/of_object.c
+++ b/c_gen/templates/of_object.c
@@ -159,23 +159,20 @@
         return NULL;
     }
 
-    object_id = of_message_to_object_id(msg, len);
-    LOCI_ASSERT(object_id != OF_OBJECT_INVALID);
-
     if ((obj = of_object_new(-1)) == NULL) {
         return NULL;
     }
 
-    of_object_init_map[object_id](obj, version, 0, 0);
-
     if (of_object_buffer_bind(obj, OF_MESSAGE_TO_BUFFER(msg), len, 
                               OF_MESSAGE_FREE_FUNCTION) < 0) {
         FREE(obj);
         return NULL;
     }
-    obj->length = len;
     obj->version = version;
 
+    of_header_wire_object_id_get(obj, &object_id);
+    of_object_init_map[object_id](obj, version, len, 0);
+
     return obj;
 }
 
@@ -213,17 +210,15 @@
         return NULL;
     }
 
-    object_id = of_message_to_object_id(msg, len);
-    /* Already validated */
-    LOCI_ASSERT(object_id != OF_OBJECT_INVALID);
-
-    of_object_init_map[object_id](obj, version, len, 0);
-
+    obj->version = version;
     obj->wire_object.wbuf = wbuf;
     wbuf->buf = msg;
     wbuf->alloc_bytes = len;
     wbuf->current_bytes = len;
 
+    of_header_wire_object_id_get(obj, &object_id);
+    of_object_init_map[object_id](obj, version, len, 0);
+
     return obj;
 }
 
diff --git a/c_gen/templates/of_type_maps.c b/c_gen/templates/of_type_maps.c
index ef3f82b..3b70f57 100644
--- a/c_gen/templates/of_type_maps.c
+++ b/c_gen/templates/of_type_maps.c
@@ -121,391 +121,6 @@
         OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_LENGTH_OFFSET), bytes);
 }
 
-/**
- * Get the type field from the wire for a standard TLV object that uses
- * uint16 for both type and length.
- * @param obj The object being referenced
- * @param wire_type (out) Where to store the type
- */
-
-static void
-of_tlv16_wire_type_get(of_object_t *obj, int *wire_type)
-{
-    uint16_t val16;
-    of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
-
-    of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 
-           TLV16_WIRE_TYPE_OFFSET), &val16);
-
-    *wire_type = val16;
-}
-
-/**
- * Get the object ID of an extended action
- * @param obj The object being referenced
- * @param id Where to store the object ID
- * @fixme:  This should be auto generated
- *
- * If unable to map to known extension, set id to generic "experimenter"
- */
-
-#define OF_ACTION_EXPERIMENTER_ID_OFFSET 4
-#define OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET 8
-
-
-static void
-extension_action_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    uint32_t exp_id;
-    uint8_t *buf;
-
-    *id = OF_ACTION_EXPERIMENTER;
-
-    buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
-    
-    buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
-
-    switch (exp_id) {
-    case OF_EXPERIMENTER_ID_BSN: {
-        uint32_t subtype;
-        buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
-        switch (subtype) {
-        case 1: *id = OF_ACTION_BSN_MIRROR; break;
-        case 2: *id = OF_ACTION_BSN_SET_TUNNEL_DST; break;
-        }
-        break;
-    }
-    case OF_EXPERIMENTER_ID_NICIRA: {
-        uint16_t subtype;
-        buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
-        switch (subtype) {
-        case 18: *id = OF_ACTION_NICIRA_DEC_TTL; break;
-        }
-        break;
-    }
-    }
-}
-
-/**
- * Get the object ID of an extended action
- * @param obj The object being referenced
- * @param id Where to store the object ID
- * @fixme:  This should be auto generated
- *
- * If unable to map to known extension, set id to generic "experimenter"
- */
-
-static void
-extension_action_id_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    uint32_t exp_id;
-    uint8_t *buf;
-
-    *id = OF_ACTION_ID_EXPERIMENTER;
-
-    buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
-    
-    buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
-
-    switch (exp_id) {
-    case OF_EXPERIMENTER_ID_BSN: {
-        uint32_t subtype;
-        buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
-        switch (subtype) {
-        case 1: *id = OF_ACTION_ID_BSN_MIRROR; break;
-        case 2: *id = OF_ACTION_ID_BSN_SET_TUNNEL_DST; break;
-        }
-        break;
-    }
-    case OF_EXPERIMENTER_ID_NICIRA: {
-        uint16_t subtype;
-        buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
-        switch (subtype) {
-        case 18: *id = OF_ACTION_ID_NICIRA_DEC_TTL; break;
-        }
-        break;
-    }
-    }
-}
-
-
-/**
- * Get the object ID based on the wire buffer for an action object
- * @param obj The object being referenced
- * @param id Where to store the object ID
- */
-
-
-void
-of_action_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_action_object_id_get(obj, id);
-        return;
-    }
-
-    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ITEM_COUNT);
-
-    *id = of_action_type_to_id[obj->version][wire_type];
-    LOCI_ASSERT(*id != OF_OBJECT_INVALID);
-}
-
-/**
- * Get the object ID based on the wire buffer for an action ID object
- * @param obj The object being referenced
- * @param id Where to store the object ID
- */
-
-
-void
-of_action_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_action_id_object_id_get(obj, id);
-        return;
-    }
-
-    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ID_ITEM_COUNT);
-
-    *id = of_action_id_type_to_id[obj->version][wire_type];
-    LOCI_ASSERT(*id != OF_OBJECT_INVALID);
-}
-
-/**
- * @fixme to do when we have instruction extensions
- * See extension_action above
- */
-
-static int
-extension_instruction_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    uint32_t exp_id;
-    uint8_t *buf;
-
-    *id = OF_INSTRUCTION_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_BSN_DISABLE_SRC_MAC_CHECK; break;
-        case 1: *id = OF_INSTRUCTION_BSN_ARP_OFFLOAD; break;
-        case 2: *id = OF_INSTRUCTION_BSN_DHCP_OFFLOAD; break;
-        case 3: *id = OF_INSTRUCTION_BSN_DISABLE_SPLIT_HORIZON_CHECK; break;
-        case 4: *id = OF_INSTRUCTION_BSN_PERMIT; break;
-        case 5: *id = OF_INSTRUCTION_BSN_DENY; break;
-        }
-        break;
-    }
-    }
-
-    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
- * @param id Where to store the object ID
- */
-
-void
-of_instruction_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_object_id_get(obj, id);
-        return;
-    }
-
-    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_INSTRUCTION_ITEM_COUNT);
-
-    *id = of_instruction_type_to_id[obj->version][wire_type];
-    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
- * See extension_action above
- */
-
-static void
-extension_queue_prop_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    (void)obj;
-
-    *id = OF_QUEUE_PROP_EXPERIMENTER;
-}
-
-/**
- * Get the object ID based on the wire buffer for an queue_prop object
- * @param obj The object being referenced
- * @param id Where to store the object ID
- */
-
-void
-of_queue_prop_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_queue_prop_object_id_get(obj, id);
-        return;
-    }
-
-    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_QUEUE_PROP_ITEM_COUNT);
-
-    *id = of_queue_prop_type_to_id[obj->version][wire_type];
-    LOCI_ASSERT(*id != OF_OBJECT_INVALID);
-}
-
-
-/**
- * Table feature property object ID determination
- *
- * @param obj The object being referenced
- * @param id Where to store the object ID
- */
-
-void
-of_table_feature_prop_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    int wire_type;
-
-    of_tlv16_wire_type_get(obj, &wire_type);
-    *id = of_table_feature_prop_to_object_id(wire_type, obj->version);
-}
-
-/**
- * Get the object ID based on the wire buffer for meter_band object
- * @param obj The object being referenced
- * @param id Where to store the object ID
- */
-
-void
-of_meter_band_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) {
-        *id = OF_METER_BAND_EXPERIMENTER;
-        return;
-    }
-
-    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_METER_BAND_ITEM_COUNT);
-
-    *id = of_meter_band_type_to_id[obj->version][wire_type];
-    LOCI_ASSERT(*id != OF_OBJECT_INVALID);
-}
-
-/**
- * Get the object ID based on the wire buffer for a hello_elem object
- * @param obj The object being referenced
- * @param id Where to store the object ID
- */
-
-void
-of_hello_elem_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    int wire_type;
-
-    of_tlv16_wire_type_get(obj, &wire_type);
-    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_HELLO_ELEM_ITEM_COUNT);
-    *id = of_hello_elem_type_to_id[obj->version][wire_type];
-    LOCI_ASSERT(*id != OF_OBJECT_INVALID);
-}
-
-/**
- * Get the object ID based on the wire buffer for a bsn_tlv object
- * @param obj The object being referenced
- * @param id Where to store the object ID
- */
-
-void
-of_bsn_tlv_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    int wire_type;
-
-    of_tlv16_wire_type_get(obj, &wire_type);
-    LOCI_ASSERT(wire_type >= 0 && wire_type < OF_BSN_TLV_ITEM_COUNT);
-    *id = of_bsn_tlv_type_to_id[obj->version][wire_type];
-    LOCI_ASSERT(*id != OF_OBJECT_INVALID);
-}
 
 /****************************************************************
  * OXM type/length functions.
@@ -551,22 +166,6 @@
     *bytes = OF_OXM_LENGTH_GET(type_len);
 }
 
-/**
- * Get the object ID of an OXM object based on the wire buffer type
- * @param obj The object whose wire buffer is an OXM type
- * @param id (out) Where the ID is stored 
- */
-
-void
-of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
-{
-    uint32_t type_len;
-    of_wire_buffer_t *wbuf;
-
-    _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
-    *id = of_oxm_to_object_id(type_len, obj->version);
-}
-
 #define OF_U16_LEN_LENGTH_OFFSET 0
 
 /**
@@ -710,65 +309,6 @@
         OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET), bytes);
 }
 
-/*
- * Non-message extension push wire values
- */
-
-int
-of_extension_object_wire_push(of_object_t *obj)
-{
-    of_action_bsn_mirror_t *action_mirror;
-    of_action_id_bsn_mirror_t *action_id_mirror;
-    of_action_bsn_set_tunnel_dst_t *action_set_tunnel_dst;
-    of_action_id_bsn_set_tunnel_dst_t *action_id_set_tunnel_dst;
-    of_action_nicira_dec_ttl_t *action_nicira_dec_ttl;
-    of_action_id_nicira_dec_ttl_t *action_id_nicira_dec_ttl;
-
-    /* Push exp type, subtype */
-    switch (obj->object_id) {
-    case OF_ACTION_BSN_MIRROR:
-        action_mirror = (of_action_bsn_mirror_t *)obj;
-        of_action_bsn_mirror_experimenter_set(action_mirror,
-            OF_EXPERIMENTER_ID_BSN);
-        of_action_bsn_mirror_subtype_set(action_mirror, 1);
-        break;
-    case OF_ACTION_ID_BSN_MIRROR:
-        action_id_mirror = (of_action_id_bsn_mirror_t *)obj;
-        of_action_id_bsn_mirror_experimenter_set(action_id_mirror,
-            OF_EXPERIMENTER_ID_BSN);
-        of_action_id_bsn_mirror_subtype_set(action_id_mirror, 1);
-        break;
-    case OF_ACTION_BSN_SET_TUNNEL_DST:
-        action_set_tunnel_dst = (of_action_bsn_set_tunnel_dst_t *)obj;
-        of_action_bsn_set_tunnel_dst_experimenter_set(action_set_tunnel_dst,
-            OF_EXPERIMENTER_ID_BSN);
-        of_action_bsn_set_tunnel_dst_subtype_set(action_set_tunnel_dst, 2);
-        break;
-    case OF_ACTION_ID_BSN_SET_TUNNEL_DST:
-        action_id_set_tunnel_dst = (of_action_id_bsn_set_tunnel_dst_t *)obj;
-        of_action_id_bsn_set_tunnel_dst_experimenter_set(action_id_set_tunnel_dst,
-            OF_EXPERIMENTER_ID_BSN);
-        of_action_id_bsn_set_tunnel_dst_subtype_set(action_id_set_tunnel_dst, 2);
-        break;
-    case OF_ACTION_NICIRA_DEC_TTL:
-        action_nicira_dec_ttl = (of_action_nicira_dec_ttl_t *)obj;
-        of_action_nicira_dec_ttl_experimenter_set(action_nicira_dec_ttl,
-            OF_EXPERIMENTER_ID_NICIRA);
-        of_action_nicira_dec_ttl_subtype_set(action_nicira_dec_ttl, 18);
-        break;
-    case OF_ACTION_ID_NICIRA_DEC_TTL:
-        action_id_nicira_dec_ttl = (of_action_id_nicira_dec_ttl_t *)obj;
-        of_action_id_nicira_dec_ttl_experimenter_set(action_id_nicira_dec_ttl,
-            OF_EXPERIMENTER_ID_NICIRA);
-        of_action_id_nicira_dec_ttl_subtype_set(action_id_nicira_dec_ttl, 18);
-        break;
-    default:
-        break;
-    }
-
-    return OF_ERROR_NONE;
-}
-
 int
 of_experimenter_stats_request_to_object_id(uint32_t experimenter, uint32_t subtype, int ver)
 {