add of_oxm_bsn_in_ports
diff --git a/c_gen/c_match.py b/c_gen/c_match.py
index c62899d..e15688e 100644
--- a/c_gen/c_match.py
+++ b/c_gen/c_match.py
@@ -286,6 +286,8 @@
     OF_OXM_INDEX_IPV6_ND_TLL    = 33, /* Target link-layer for ND. */
     OF_OXM_INDEX_MPLS_LABEL     = 34, /* MPLS label. */
     OF_OXM_INDEX_MPLS_TC        = 35, /* MPLS TC. */
+
+    OF_OXM_INDEX_BSN_IN_PORTS_128 = 36,
 };
 
 #define OF_OXM_BIT(index) (((uint64_t) 1) << (index))
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index a0fec7e..3c523b4 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -507,6 +507,52 @@
 }
 """
 
+    oxm_template = """
+/**
+ * oxm wire type to object ID array.
+ * Treat as private; use function accessor below
+ */
+
+extern const of_object_id_t *const of_oxm_type_to_id[OF_VERSION_ARRAY_MAX];
+
+#define OF_OXM_ITEM_COUNT %(ar_len)d\n
+
+/**
+ * Map an oxm wire value to an OF object
+ * @param oxm The oxm type wire value
+ * @param version The version associated with the check
+ * @return The oxm OF object type
+ * @return OF_OBJECT_INVALID if type does not map to an object
+ *
+ */
+static inline of_object_id_t
+of_oxm_to_object_id(uint32_t type_len, of_version_t version)
+{
+    if (!OF_VERSION_OKAY(version)) {
+        return OF_OBJECT_INVALID;
+    }
+
+    uint16_t class = (type_len >> 16) & 0xffff;
+    uint8_t masked_type = (type_len >> 8) & 0xff;
+
+    if (class == 0x8000) {
+        if (masked_type < 0 || masked_type >= OF_OXM_ITEM_COUNT) {
+            return OF_OBJECT_INVALID;
+        }
+
+        return of_oxm_type_to_id[version][masked_type];
+    } else if (class == 0x0003) {
+        switch (masked_type) {
+        case 0x00: return OF_OXM_BSN_IN_PORTS_128;
+        case 0x01: return OF_OXM_BSN_IN_PORTS_128_MASKED;
+        default: return OF_OBJECT_INVALID;
+        }
+    } else {
+        return OF_OBJECT_INVALID;
+    }
+}
+"""
+
     # Action types array gen
     ar_len = type_maps.type_array_len(type_maps.action_types, max_type_value)
     out.write(map_with_experimenter_template %
@@ -561,13 +607,14 @@
     out.write(map_template %
               dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))
 
+    # OXM
     ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
     out.write("""
 /* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
 """)
-    out.write(map_template %
-              dict(name="oxm", u_name="OXM", ar_len=ar_len))
+    out.write(oxm_template % dict(ar_len=ar_len))
 
+    # Messages
     out.write(experimenter_function)
     # Must follow stats reply/request
     ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
@@ -1003,11 +1050,6 @@
 extern void of_hello_elem_wire_object_id_get(of_object_t *obj,
     of_object_id_t *id);
 
-/* XXX Hardcoded to the OpenFlow Basic OXM class */
-#define OF_OXM_MASKED_TYPE_GET(hdr) (((hdr) >> 8) & 0xff)
-#define OF_OXM_MASKED_TYPE_SET(hdr, val)                    \\
-    (hdr) = ((hdr) & 0x000000ff) + 0x80000000 + (((val) & 0xff) << 8)
-
 #define OF_OXM_LENGTH_GET(hdr) (((hdr) & 0xff) + 4)
 #define OF_OXM_LENGTH_SET(hdr, val)                         \\
     (hdr) = ((hdr) & 0xffffff00) + (((val) - 4) & 0xff)
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index 0cf9133..d2ba8f4 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -339,6 +339,9 @@
 #define LOCI_SHOW_ipv4_value_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
 #define LOCI_SHOW_u8_hybrid_enable(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
 #define LOCI_SHOW_u16_hybrid_version(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_bitmap_128_value(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
+#define LOCI_SHOW_bitmap_128_value_mask(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
+#define LOCI_SHOW_bitmap_128_bsn_in_ports_128(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
 
 
 #endif /* _LOCI_SHOW_H_ */
diff --git a/c_gen/templates/of_type_maps.c b/c_gen/templates/of_type_maps.c
index 2c1032d..67c3535 100644
--- a/c_gen/templates/of_type_maps.c
+++ b/c_gen/templates/of_type_maps.c
@@ -559,12 +559,10 @@
 of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
 {
     uint32_t type_len;
-    int wire_type;
     of_wire_buffer_t *wbuf;
 
     _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
-    wire_type = OF_OXM_MASKED_TYPE_GET(type_len);
-    *id = of_oxm_to_object_id(wire_type, obj->version);
+    *id = of_oxm_to_object_id(type_len, obj->version);
 }
 
 /**
@@ -584,9 +582,21 @@
 
     /* Read-modify-write */
     _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
-    wire_type = of_object_to_wire_type(id, obj->version);
-    ASSERT(wire_type >= 0);
-    OF_OXM_MASKED_TYPE_SET(type_len, wire_type);
+
+    switch (id) {
+    case OF_OXM_BSN_IN_PORTS_128:
+        type_len = 0x00030000 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_IN_PORTS_128_MASKED:
+        type_len = 0x00030100 | (type_len & 0xff);
+        break;
+    default:
+        wire_type = of_object_to_wire_type(id, obj->version);
+        ASSERT(wire_type >= 0);
+        type_len = 0x80000000 | (wire_type << 8) | (type_len & 0xff);
+        break;
+    }
+
     of_wire_buffer_u32_set(wbuf, 
            OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), type_len);
 }