Merge branch 'master' into wireshark
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index df9d9da..798f5a4 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -1007,6 +1007,11 @@
 typedef char of_desc_str_t[OF_DESC_STR_LEN];
 typedef char of_serial_num_t[OF_SERIAL_NUM_LEN];
 
+typedef struct of_bitmap_128_s {
+    uint64_t hi;
+    uint64_t lo;
+} of_bitmap_128_t;
+
 /* These are types which change across versions.  */
 typedef uint32_t of_port_no_t;
 typedef uint16_t of_fm_cmd_t;
diff --git a/c_gen/c_match.py b/c_gen/c_match.py
index 7353ae7..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))
@@ -1066,6 +1068,15 @@
 #define OF_OVERLAP_MAC_ADDR(v1, v2, m1, m2) \\
     of_overlap_mac_addr((v1), (v2), (m1), (m2))
 
+#define OF_MORE_SPECIFIC_BITMAP_128(v1, v2) \\
+    (OF_MORE_SPECIFIC_INT((v1)->lo, (v2)->lo) && OF_MORE_SPECIFIC_INT((v1)->hi, (v2)->hi))
+
+#define OF_RESTRICTED_MATCH_BITMAP_128(v1, v2, mask) \\
+    (OF_RESTRICTED_MATCH_INT((v1)->lo, (v2)->lo, (mask)->lo) && OF_RESTRICTED_MATCH_INT((v1)->hi, (v2)->hi, (mask)->hi))
+
+#define OF_OVERLAP_BITMAP_128(v1, v2, m1, m2) \\
+    (OF_OVERLAP_INT((v1)->lo, (v2)->lo, (m1)->lo, (m2)->lo) && OF_OVERLAP_INT((v1)->hi, (v2)->hi, (m1)->hi, (m2)->hi))
+
 /**
  * More-specific-than macro for integer types; see above
  * @return true if v1 is equal to or more specific than v2
@@ -1136,6 +1147,9 @@
         elif entry["m_type"] == "of_mac_addr_t":
             comp = "OF_MORE_SPECIFIC_MAC_ADDR"
             match_type = "OF_RESTRICTED_MATCH_MAC_ADDR"
+        elif entry["m_type"] == "of_bitmap_128_t":
+            comp = "OF_MORE_SPECIFIC_BITMAP_128"
+            match_type = "OF_RESTRICTED_MATCH_BITMAP_128"
         else: # Integer
             comp = "OF_MORE_SPECIFIC_INT"
             match_type = "OF_RESTRICTED_MATCH_INT"
@@ -1190,6 +1204,8 @@
             check = "OF_OVERLAP_IPV6"
         elif entry["m_type"] == "of_mac_addr_t":
             check = "OF_OVERLAP_MAC_ADDR"
+        elif entry["m_type"] == "of_bitmap_128_t":
+            check = "OF_OVERLAP_BITMAP_128"
         else: # Integer
             check = "OF_OVERLAP_INT"
             m1 = "m1->%s" % key
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index fab9f96..d237cfe 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -98,6 +98,7 @@
         of_match_t="match",
         # BSN extensions
         of_bsn_vport_q_in_q_t="vport",
+        of_bitmap_128_t="bitmap_128",
         )
 
     if m_type.find("of_list_") == 0:
@@ -111,7 +112,7 @@
                  "of_match_bmap_t", "of_ipv4_t"]
 string_types = [ "of_port_name_t", "of_table_name_t",
                 "of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
-                "of_ipv6_t"]
+                "of_ipv6_t", "of_bitmap_128_t"]
 
 scalar_types = integer_types[:]
 scalar_types.extend(string_types)
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index a0fec7e..9644fdb 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,10 +547,64 @@
         }
     }
 
+    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;
 }
 """
 
+    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 %
@@ -557,17 +655,24 @@
               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))
 
+    # 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)
@@ -725,6 +830,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 +1035,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 an error 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);
@@ -1003,11 +1152,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_dump.h b/c_gen/templates/loci_dump.h
index c2fd53a..d44832a 100644
--- a/c_gen/templates/loci_dump.h
+++ b/c_gen/templates/loci_dump.h
@@ -94,6 +94,8 @@
 int loci_dump_match(loci_writer_f writer, void* cookie, of_match_t *match);
 #define LOCI_DUMP_match(writer, cookie, val) loci_dump_match(writer, cookie, &val)
 
+#define LOCI_DUMP_bitmap_128(writer, cookie, val) writer(cookie, "%" PRIx64 "%" PRIx64, (val).hi, (val).lo)
+
 /**
  * Generic version for any object
  */
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index 948ee92..215e65a 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -162,6 +162,8 @@
 int loci_show_match(loci_writer_f writer, void *cookie, of_match_t *match);
 #define LOCI_SHOW_match(writer, cookie, val) loci_show_match(writer, cookie, &val)
 
+#define LOCI_SHOW_bitmap_128(writer, cookie, val) writer(cookie, "%" PRIx64 "%" PRIx64, (val).hi, (val).lo)
+
 /**
  * Generic version for any object
  */
@@ -337,6 +339,11 @@
 #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)
+#define LOCI_SHOW_u32_timeout_ms(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u32_tx_interval_ms(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u8_slot_num(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
 
 #endif /* _LOCI_SHOW_H_ */
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/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);
 }
diff --git a/c_gen/templates/of_wire_buf.h b/c_gen/templates/of_wire_buf.h
index 8750565..117332c 100644
--- a/c_gen/templates/of_wire_buf.h
+++ b/c_gen/templates/of_wire_buf.h
@@ -876,6 +876,30 @@
 #define of_wire_buffer_ipv6_set(buf, offset, addr) \
     _wbuf_octets_set(buf, offset, (uint8_t *)&addr, sizeof(of_ipv6_t))
 
+/**
+ * Get an bitmap_128 address from a wire buffer
+ * @param wbuf The pointer to the wire buffer structure
+ * @param offset Offset in the wire buffer
+ * @param addr Pointer to where to store the bitmap_128 address
+ *
+ * Uses the octets function.
+ */
+
+#define of_wire_buffer_bitmap_128_get(buf, offset, addr) \
+    (of_wire_buffer_u64_get(buf, offset, &addr->hi), of_wire_buffer_u64_get(buf, offset+8, &addr->lo))
+
+/**
+ * Set an bitmap_128 address in a wire buffer
+ * @param wbuf The pointer to the wire buffer structure
+ * @param offset Offset in the wire buffer
+ * @param addr The variable holding bitmap_128 address to store
+ *
+ * Uses the octets function.
+ */
+
+#define of_wire_buffer_bitmap_128_set(buf, offset, addr) \
+    (of_wire_buffer_u64_set(buf, offset, addr.hi), of_wire_buffer_u64_set(buf, offset+8, addr.lo))
+
 /* Relocate data from start offset to the end of the buffer to a new position */
 static inline void
 of_wire_buffer_move_end(of_wire_buffer_t *wbuf, int start_offset, int new_offset)
diff --git a/java_gen/codegen.py b/java_gen/codegen.py
index d94d78a..776b8c5 100644
--- a/java_gen/codegen.py
+++ b/java_gen/codegen.py
@@ -50,7 +50,6 @@
         shutil.rmtree(basedir)
     os.makedirs(basedir)
     copy_prewrite_tree(basedir)
-    java_model.adjust_ir()
     gen = JavaGenerator(basedir)
     gen.create_of_interfaces()
     gen.create_of_classes()
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 410a1dd..2963f2d 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -46,101 +46,10 @@
 import java_gen.java_type as java_type
 from java_gen.java_type import erase_type_annotation
 
-# Key is modified name of error code; value is OFErrorType value string
-error_type_map = {}
-
-def adjust_ir():
-    """
-    For Java we change of_error_message to combine the 16-bit type and code
-    fields into a single 32-bit code field and we combine the per-error-type
-    code enums into a single ofp_error_code enum. This enables the generated
-    OFErrorMsg class to have a getCode method that can return all supported
-    error codes. Otherwise we'd need to do something like having per-error-type
-    subclasses of OFErrorMsg that had a getCode that returned the different
-    error codes for each error type, which would be less convenient for clients
-    and would also entail changing the LOXI OF input files and impacting other
-    language backends.
-    """
-    for version in of_g.target_version_list:
-        of_protocol = of_g.ir[version]
-        error_type = find(lambda e: e.name == "ofp_error_type", of_protocol.enums)
-        if error_type == None:
-            raise Exception("ofp_error_type enum not found; OF version: " + str(version))
-        error_code_entries = []
-        # For each error type value look up the corresponding error code enum.
-        # Add those values to the combined entries for the new ofp_error_code
-        # enum. The name of the new value is formed by concatenating the name
-        # of the error type value with the name of the old error code value.
-        for error_type_entry in error_type.entries:
-            # Strip off the OFPxx prefix
-            prefix_length = error_type_entry.name.find('_')
-            if prefix_length < 0:
-                raise Exception("OFPET prefix not found for ofp_error_type value " + error_type_entry.name + "; OF version: " + str(version))
-            error_type_entry_name = error_type_entry.name[prefix_length+1:]
-            if error_type_entry_name == "EXPERIMENTER":
-                # There isn't an error code enum defined for the experimenter error type
-                # FIXME: Need to add support for the message ofp_error_experimenter_msg format
-                continue
-            # The per-error-type code enums follow a naming conventions where
-            # the middle part of the enum name is the same as the name of the
-            # error type value (except lower-case).
-            error_code_enum_name = "ofp_" + error_type_entry_name.lower() + "_code"
-            # Look up the error code enum from the IR
-            error_code_enum = None
-            for i, enum in enumerate(of_protocol.enums):
-                if enum.name == error_code_enum_name:
-                    error_code_enum = enum
-                    # We don't want to generate code for the per-error-type
-                    # enum so remove it from the IR
-                    del of_protocol.enums[i]
-                    break
-            if error_code_enum == None:
-                raise Exception("Error code enum not found: " + error_code_enum_name + "; OF version: " + str(version))
-            for error_code_entry in error_code_enum.entries:
-                # Strip off the prefix from the entry name
-                prefix_length = error_code_entry.name.find('_')
-                if prefix_length < 0:
-                    raise Exception("Prefix not found for error code value " + error_code_entry.name + "; OF version: " + str(version))
-                error_code_entry_name = error_code_entry.name[prefix_length+1:]
-                # Combine the entry type name and the error code name
-                error_code_entry_name = error_type_entry_name + "_" + error_code_entry_name
-                # Combine the entry type value and the error code value
-                error_code_entry_value = (error_type_entry.value << 16) + error_code_entry.value
-                # Add the enum entry to the combined ofp_error_code
-                # Note that the "OFPEC" prefix is arbitrary. It will be stripped
-                # off again during Java code generation, but there needs to be
-                # some/any prefix
-                error_code_entries.append(OFEnumEntry("OFPEC_" + error_code_entry_name, error_code_entry_value, {}))
-                error_type_map[error_code_entry_name] = error_type_entry_name
-        # We've collected all of the entries. Now we can add the enum to the IR
-        of_protocol.enums.append(OFEnum("ofp_error_code", error_code_entries, {'wire_type': 'uint32_t'}))
-
-        # We also need to patch the of_error_msg class to combine the 16-bit error
-        # type and code fields into a single 32-bit error code field
-        error_msg = find(lambda c: c.name == "of_error_msg", of_protocol.classes)
-        if error_msg == None:
-            raise Exception("of_error_msg class not found; OF version: " + str(version))
-        err_type_index = None
-        for i, member in enumerate(error_msg.members):
-            if member.name == "err_type":
-                # Keep track of the error type index so we can remove it once
-                # we've finished iterating
-                err_type_index = i
-            elif member.name == 'code':
-                # Change the code to be a 32-bit ofp_error_code enum value
-                error_msg.members[i] = OFDataMember("code", "ofp_error_code")
-        if err_type_index == None:
-            raise Exception("err_type member of of_error_msg not found; OF version: " + str(version))
-        del error_msg.members[err_type_index]
-
-
-def gen_error_type(enum_entry):
-    return "OFErrorType." + error_type_map[enum_entry.name]
-
 class JavaModel(object):
     # registry for enums that should not be generated
     # set(${java_enum_name})
-    enum_blacklist = set(("OFDefinitions", "OFPortNo",))
+    enum_blacklist = set(("OFDefinitions", "OFPortNo", "OFVlanId"))
     # registry for enum *entry* that should not be generated
     # map: ${java_enum_name} -> set(${java_entry_entry_name})
     enum_entry_blacklist = defaultdict(lambda: set(), OFFlowWildcards=set([ "NW_DST_BITS", "NW_SRC_BITS", "NW_SRC_SHIFT", "NW_DST_SHIFT" ]))
@@ -229,7 +138,9 @@
                 "OFOxmMplsLabel":           OxmMapEntry("U32", "MPLS_LABEL", False),
                 "OFOxmMplsLabelMasked":     OxmMapEntry("U32", "MPLS_LABEL", True),
                 "OFOxmMplsTc":              OxmMapEntry("U8", "MPLS_TC", False),
-                "OFOxmMplsTcMasked":        OxmMapEntry("U8", "MPLS_TC", True)
+                "OFOxmMplsTcMasked":        OxmMapEntry("U8", "MPLS_TC", True),
+                "OFOxmBsnInPorts128":       OxmMapEntry("OFBitMask128", "BSN_IN_PORTS_128", False),
+                "OFOxmBsnInPorts128Masked": OxmMapEntry("OFBitMask128", "BSN_IN_PORTS_128", True)
                 }
 
     # Registry of nullable properties:
@@ -299,7 +210,6 @@
     enum_metadata_map = defaultdict(lambda: JavaModel.OFEnumMetadata((), None),
             OFPortFeatures = OFEnumMetadata((OFEnumPropertyMetadata("PortSpeed", java_type.port_speed, gen_port_speed),), None),
             OFPortState = OFEnumMetadata((OFEnumPropertyMetadata("StpState", java_type.boolean, gen_stp_state),), None),
-            OFErrorCode = OFEnumMetadata((OFEnumPropertyMetadata("ErrorType", java_type.error_type, gen_error_type),), None),
     )
 
     @property
@@ -399,6 +309,13 @@
                         factory.members.append(i)
                         break
         return factories.values()
+    
+    @memoize
+    def factory_of(self, interface):
+        for factory in self.of_factories:
+            if interface in factory.members:
+                return factory
+        return None
 
     def generate_class(self, clazz):
         """ return wether or not to generate implementation class clazz.
@@ -441,6 +358,12 @@
             return "build" + n[0].upper() + n[1:]
         else:
             return n
+    
+    def of_version(self, version):
+        for fc in self.factory_classes:
+            if fc.version == version:
+                return fc
+        return None
 
 OFGenericClass = namedtuple("OFGenericClass", ("package", "name"))
 class OFFactoryClass(namedtuple("OFFactoryClass", ("package", "name", "interface", "version"))):
@@ -579,6 +502,8 @@
             return ("", "OFStatsRequest<{}>".format(re.sub(r'Request$', 'Reply', self.name)), None)
         elif re.match(r'OF.+StatsReply$', self.name):
             return ("", "OFStatsReply", None)
+        elif re.match(r'OF.+ErrorMsg$', self.name):
+            return ("", "OFErrorMsg", None)
         elif re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
             return ("", "OFFlowMod", None)
         elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFBsn.+$', self.name) and self.name != "OFBsnHeader":
@@ -656,29 +581,30 @@
 
     @property
     def virtual_members(self):
+        virtual_members = []
         if self.name == "OFOxm":
-            return (
+            virtual_members += [
                     JavaVirtualMember(self, "value", java_type.generic_t),
                     JavaVirtualMember(self, "mask", java_type.generic_t),
                     JavaVirtualMember(self, "matchField", java_type.make_match_field_jtype("T")),
                     JavaVirtualMember(self, "masked", java_type.boolean),
-                   )
+                   ]
         elif self.parent_interface and self.parent_interface.startswith("OFOxm"):
             field_type = java_type.make_match_field_jtype(model.oxm_map[self.name].type_name) \
                 if self.name in model.oxm_map \
                 else java_type.make_match_field_jtype()
 
-            return (
+            virtual_members += [
                     JavaVirtualMember(self, "matchField", field_type),
                     JavaVirtualMember(self, "masked", java_type.boolean),
-                   ) \
-                   + \
-                   (
-                           ( JavaVirtualMember(self, "mask", find(lambda x: x.name == "value", self.ir_model_members).java_type), ) if not find(lambda x: x.name == "mask", self.ir_model_members) else
-                    ()
-                   )
-        else:
-            return ()
+                   ]
+            if not find(lambda x: x.name == "mask", self.ir_model_members):
+                virtual_members.append(JavaVirtualMember(self, "mask", find(lambda x: x.name == "value", self.ir_model_members).java_type))
+
+        if not find(lambda m: m.name == "version", self.ir_model_members):
+            virtual_members.append(JavaVirtualMember(self, "version", java_type.of_version))
+
+        return tuple(virtual_members)
 
     @property
     @memoize
@@ -791,26 +717,31 @@
         return self.ir_model_members + self.virtual_members
 
     @property
+    @memoize
     def ir_model_members(self):
         members = [ JavaMember.for_of_member(self, of_member) for of_member in self.ir_class.members ]
         return tuple(members)
 
     @property
     def virtual_members(self):
+        virtual_members = []
         if self.interface.parent_interface and self.interface.parent_interface.startswith("OFOxm"):
             if self.interface.name in model.oxm_map:
                 oxm_entry = model.oxm_map[self.interface.name]
-                return (
+                virtual_members += [
                     JavaVirtualMember(self, "matchField", java_type.make_match_field_jtype(oxm_entry.type_name), "MatchField.%s" % oxm_entry.value),
                     JavaVirtualMember(self, "masked", java_type.boolean, "true" if oxm_entry.masked else "false"),
-                   )
+                   ]
             else:
-                return (
+                virtual_members += [
                     JavaVirtualMember(self, "matchField", java_type.make_match_field_jtype(), "null"),
                     JavaVirtualMember(self, "masked", java_type.boolean, "false"),
-                   )
-        else:
-            return ()
+                   ]
+
+        if not find(lambda m: m.name == "version", self.ir_model_members):
+            virtual_members.append(JavaVirtualMember(self, "version", java_type.of_version, "OFVersion.%s" % self.version.constant_version))
+
+        return tuple(virtual_members)
 
     def all_versions(self):
         return [ JavaOFVersion(int_version)
@@ -1113,7 +1044,11 @@
     @property
     def name(self):
         return self.test_class_name
-
+    
+    @property
+    def interface(self):
+        return self.java_class.interface
+    
     @property
     def has_test_data(self):
         return test_data.exists(self.data_file_name)
@@ -1132,10 +1067,7 @@
     def __init__(self, c_name, version_enum_map):
         self.c_name = c_name
 
-        if c_name == "of_stats_types":
-            self.name = "OFStatsType"
-        else:
-            self.name   = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
+        self.name   = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
 
         # Port_features has constants that start with digits
         self.name_prefix = "PF_" if self.name == "OFPortFeatures" else ""
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 7da6f6a..169b3f0 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -33,11 +33,12 @@
     else:
         return camel
 
-java_primitive_types = set("byte char short int long".split(" "))
+java_primitive_types = set("boolean byte char short int long".split(" "))
 
 ### info table about java primitive types, for casting literals in the source code
 # { name : (signed?, length_in_bits) }
 java_primitives_info = {
+        'boolean' : (False, 8),
         'byte' : (True, 8),
         'char' : (False, 16),
         'short' : (True, 16),
@@ -48,7 +49,7 @@
 def format_primitive_literal(t, value):
     """ Format a primitive numeric literal for inclusion in the
         java source code. Takes care of casting the literal
-        apropriately for correct representation despite Java's
+        appropriately for correct representation despite Java's
         signed-craziness
     """
     signed, bits = java_primitives_info[t]
@@ -227,7 +228,8 @@
 # FIXME: This list needs to be pruned / cleaned up. Most of these are schematic.
 
 u8 =  JType('short', 'byte') \
-        .op(read='bb.readByte()', write='bb.writeByte($name)')
+        .op(read='U8.f(bb.readByte())', write='bb.writeByte(U8.t($name))', pub_type=True) \
+        .op(read='bb.readByte()', write='bb.writeByte($name)', pub_type=False)
 u8_list =  JType('List<U8>') \
         .op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)')
 u16 = JType('int', 'short') \
@@ -250,6 +252,9 @@
 of_port = JType("OFPort") \
          .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFPort.ANY") \
          .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFPort.ANY")
+# the same OFPort, but with a default value of ZERO, only for OF10 match
+of_port_match_v1 = JType("OFPort") \
+         .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFPort.ZERO")
 actions_list = JType('List<OFAction>') \
         .op(read='ChannelUtils.readList(bb, $length, OFActionVer$version.READER)',
             write='ChannelUtils.writeList(bb, $name);',
@@ -279,7 +284,8 @@
             default="new byte[0]");
 of_match = JType('Match') \
         .op(read='ChannelUtilsVer$version.readOFMatch(bb)', \
-            write='$name.writeTo(bb)');
+            write='$name.writeTo(bb)',
+            default="OFFactoryVer$version.MATCH_WILDCARD_ALL");
 flow_mod_cmd = JType('OFFlowModCommand', 'short') \
         .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \
         .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)")
@@ -323,9 +329,9 @@
             write="$name.write2Bytes(bb)",
             default="EthType.NONE")
 vlan_vid = JType("VlanVid")\
-        .op(read="VlanVid.read2Bytes(bb)",
-            write="$name.write2Bytes(bb)",
-            default="VlanVid.NONE")
+        .op(version=1, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \
+        .op(version=2, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \
+        .op(version=ANY, read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="VlanVid.NONE")
 vlan_pcp = JType("VlanPcp")\
         .op(read="VlanPcp.readByte(bb)",
             write="$name.writeByte(bb)",
@@ -380,14 +386,27 @@
 table_stats_wildcards = JType("int") \
         .op(read='bb.readInt()',
             write='bb.writeInt($name)')
+port_bitmap = JType('OFBitMask128') \
+            .op(read='OFBitMask128.read16Bytes(bb)',
+                write='$name.write16Bytes(bb)',
+                default='OFBitMask128.NONE')
 table_id = JType("TableId") \
         .op(read='TableId.readByte(bb)',
             write='$name.writeByte(bb)',
             default='TableId.ALL')
+of_version = JType("OFVersion", 'byte') \
+            .op(read='bb.readByte()', write='bb.writeByte($name)')
 
 port_speed = JType("PortSpeed")
 error_type = JType("OFErrorType")
-boolean = JType("boolean").op(default="false")
+boolean = JType("boolean", "byte") \
+        .op(read='(bb.readByte() != 0)',
+            write='bb.writeByte($name ? 1 : 0)',
+            default="false")
+datapath_id = JType("DatapathId") \
+        .op(read='DatapathId.of(bb.readLong())',
+            write='bb.writeLong($name.getLong())',
+            default='DatapathId.NONE')
 
 generic_t = JType("T")
 
@@ -420,6 +439,7 @@
         'of_wc_bmap_t': flow_wildcards,
         'of_oxm_t': oxm,
         'of_meter_features_t': meter_features,
+        'of_bitmap_128_t': port_bitmap
         }
 
 ## Map that defines exceptions from the standard loxi->java mapping scheme
@@ -473,12 +493,18 @@
         'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
         'of_oxm_mpls_tc' : { 'value' : u8obj },
         'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
+        
+        'of_oxm_bsn_in_ports_128' : { 'value': port_bitmap },
+        'of_oxm_bsn_in_ports_128_masked' : { 'value': port_bitmap, 'value_mask': port_bitmap },
 
         'of_table_stats_entry': { 'wildcards': table_stats_wildcards },
         'of_match_v1': { 'vlan_vid' : vlan_vid, 'vlan_pcp': vlan_pcp,
                 'eth_type': eth_type, 'ip_dscp': ip_dscp, 'ip_proto': ip_proto,
-                'tcp_src': transport_port, 'tcp_dst': transport_port
-                }
+                'tcp_src': transport_port, 'tcp_dst': transport_port,
+                'in_port': of_port_match_v1
+                },
+        'of_bsn_set_l2_table_request': { 'l2_table_enable': boolean },
+        'of_bsn_set_l2_table_reply': { 'l2_table_enable': boolean },
 }
 
 
@@ -541,14 +567,30 @@
         return JType("OFActionType", 'short') \
             .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
             .op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
+    elif field_name == "err_type":
+        return JType("OFErrorType", 'short') \
+            .op(read='bb.readShort()', write='bb.writeShort($name)')
+    elif field_name == "stats_type":
+        return JType("OFStatsType", 'short') \
+            .op(read='bb.readShort()', write='bb.writeShort($name)')
+    elif field_name == "type" and re.match(r'of_instruction.*', obj_name):
+        return JType("OFInstructionType", 'short') \
+            .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
+            .op(read="OFInstructionTypeSerializerVer$version.readFrom(bb)", write="OFInstructionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
     elif field_name == "table_id" and c_type == "uint8_t":
         return table_id
     elif field_name == "version" and c_type == "uint8_t":
-        return JType("OFVersion", 'byte') \
-            .op(read='bb.readByte()', write='bb.writeByte($name)')
+        return of_version
     elif field_name == "buffer_id" and c_type == "uint32_t":
         return JType("OFBufferId") \
             .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())", default="OFBufferId.NO_BUFFER")
+    elif field_name == 'datapath_id':
+        return datapath_id
+    elif field_name == 'actions' and obj_name == 'of_features_reply':
+        return JType("Set<OFActionType>") \
+            .op(read='ChannelUtilsVer10.readSupportedActions(bb)',
+                write='ChannelUtilsVer10.writeSupportedActions(bb, $name)',
+                default='ImmutableSet.<OFActionType>of()')
     elif c_type in default_mtype_to_jtype_convert_map:
         return default_mtype_to_jtype_convert_map[c_type]
     elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java
index 07759d7..852b803 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java
@@ -5,4 +5,5 @@
  * Base interface of all OpenFlow objects (e.g., messages, actions, stats, etc.)
  */
 public interface OFObject extends Writeable {
+    OFVersion getVersion();
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
index 47ca9da..5df7012 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
@@ -13,6 +13,7 @@
 import org.projectfloodlight.openflow.types.MacAddress;
 import org.projectfloodlight.openflow.types.OFMetadata;
 import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.OFBitMask128;
 import org.projectfloodlight.openflow.types.OFValueType;
 import org.projectfloodlight.openflow.types.TransportPort;
 import org.projectfloodlight.openflow.types.U32;
@@ -170,6 +171,9 @@
             new MatchField<U8>("mpls_tc", MatchFields.MPLS_TC,
                     new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.MPLS_UNICAST, EthType.MPLS_MULTICAST));
 
+    public final static MatchField<OFBitMask128> BSN_IN_PORTS_128 =
+            new MatchField<OFBitMask128>("bsn_in_port_masked_128", MatchFields.BSN_IN_PORTS_128);
+
     public String getName() {
         return name;
     }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
index 7deb9af..0de5caf 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
@@ -37,5 +37,6 @@
     IPV6_ND_SLL,
     IPV6_ND_TLL,
     MPLS_LABEL,
-    MPLS_TC
+    MPLS_TC,
+    BSN_IN_PORTS_128
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java
index 7a42d20..3f2f23f 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java
@@ -1,9 +1,13 @@
 package org.projectfloodlight.openflow.protocol.ver10;
 
+import java.util.EnumSet;
+import java.util.Set;
+
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 import org.projectfloodlight.openflow.protocol.match.Match;
 import org.projectfloodlight.openflow.protocol.ver10.OFMatchV1Ver10;
+import org.projectfloodlight.openflow.protocol.OFActionType;
 import org.projectfloodlight.openflow.protocol.OFBsnVportQInQ;
 
 /**
@@ -28,4 +32,63 @@
 
     }
 
+    public static Set<OFActionType> readSupportedActions(ChannelBuffer bb) {
+        int actions = bb.readInt();
+        EnumSet<OFActionType> supportedActions = EnumSet.noneOf(OFActionType.class);
+        if ((actions & (1 << OFActionTypeSerializerVer10.OUTPUT_VAL)) != 0)
+            supportedActions.add(OFActionType.OUTPUT);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_VLAN_VID_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_VLAN_VID);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_VLAN_PCP_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_VLAN_PCP);
+        if ((actions & (1 << OFActionTypeSerializerVer10.STRIP_VLAN_VAL)) != 0)
+            supportedActions.add(OFActionType.STRIP_VLAN);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_DL_SRC_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_DL_SRC);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_DL_DST_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_DL_DST);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_NW_SRC_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_NW_SRC);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_NW_DST_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_NW_DST);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_NW_TOS_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_NW_TOS);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_TP_SRC_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_TP_SRC);
+        if ((actions & (1 << OFActionTypeSerializerVer10.SET_TP_DST_VAL)) != 0)
+            supportedActions.add(OFActionType.SET_TP_DST);
+        if ((actions & (1 << OFActionTypeSerializerVer10.ENQUEUE_VAL)) != 0)
+            supportedActions.add(OFActionType.ENQUEUE);
+        return supportedActions;
+    }
+
+    public static void writeSupportedActions(ChannelBuffer bb,
+            Set<OFActionType> supportedActions) {
+        int supportedActionsVal = 0;
+        if (supportedActions.contains(OFActionType.OUTPUT))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.OUTPUT_VAL);
+        if (supportedActions.contains(OFActionType.SET_VLAN_VID))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_VLAN_VID_VAL);
+        if (supportedActions.contains(OFActionType.SET_VLAN_PCP))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_VLAN_PCP_VAL);
+        if (supportedActions.contains(OFActionType.STRIP_VLAN))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.STRIP_VLAN_VAL);
+        if (supportedActions.contains(OFActionType.SET_DL_SRC))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_DL_SRC_VAL);
+        if (supportedActions.contains(OFActionType.SET_DL_DST))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_DL_DST_VAL);
+        if (supportedActions.contains(OFActionType.SET_NW_SRC))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_NW_SRC_VAL);
+        if (supportedActions.contains(OFActionType.SET_NW_DST))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_NW_DST_VAL);
+        if (supportedActions.contains(OFActionType.SET_NW_TOS))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_NW_TOS_VAL);
+        if (supportedActions.contains(OFActionType.SET_TP_SRC))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_TP_SRC_VAL);
+        if (supportedActions.contains(OFActionType.SET_TP_DST))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_TP_DST_VAL);
+        if (supportedActions.contains(OFActionType.ENQUEUE))
+            supportedActionsVal |= (1 << OFActionTypeSerializerVer10.ENQUEUE_VAL);
+        bb.writeInt(supportedActionsVal);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
similarity index 73%
rename from java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java
rename to java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
index 4764747..a6f2106 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
@@ -5,23 +5,23 @@
 import com.google.common.primitives.UnsignedInts;
 
 @Immutable
-public class Metadata implements OFValueType<Metadata> {
+public class ClassId implements OFValueType<ClassId> {
     static final int LENGTH = 4;
 
     private final static int NONE_VAL = 0;
-    public final static Metadata NONE = new Metadata(NONE_VAL);
+    public final static ClassId NONE = new ClassId(NONE_VAL);
 
     private final int rawValue;
 
-    private Metadata(final int rawValue) {
+    private ClassId(final int rawValue) {
         this.rawValue = rawValue;
     }
 
-    public static Metadata of(final int raw) {
+    public static ClassId of(final int raw) {
         if(raw == NONE_VAL)
             return NONE;
 
-        return new Metadata(raw);
+        return new ClassId(raw);
     }
 
     public int getInt() {
@@ -39,8 +39,8 @@
     }
 
     @Override
-    public Metadata applyMask(Metadata mask) {
-        return Metadata.of(rawValue & mask.rawValue);    }
+    public ClassId applyMask(ClassId mask) {
+        return ClassId.of(rawValue & mask.rawValue);    }
 
     @Override
     public int hashCode() {
@@ -58,14 +58,14 @@
             return false;
         if (getClass() != obj.getClass())
             return false;
-        Metadata other = (Metadata) obj;
+        ClassId other = (ClassId) obj;
         if (rawValue != other.rawValue)
             return false;
         return true;
     }
 
     @Override
-    public int compareTo(Metadata o) {
+    public int compareTo(ClassId o) {
         return UnsignedInts.compare(rawValue, rawValue);
     }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java
new file mode 100644
index 0000000..aa7191a
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java
@@ -0,0 +1,63 @@
+package org.projectfloodlight.openflow.types;
+
+import org.projectfloodlight.openflow.util.HexString;
+
+/**
+ * Abstraction of a datapath ID that can be set and/or accessed as either a
+ * long value or a colon-separated string.
+ * 
+ * @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
+ */
+public class DatapathId {
+
+    public static final DatapathId NONE = new DatapathId(0);
+
+    private final long rawValue;
+
+    private DatapathId(long rawValue) {
+        this.rawValue = rawValue;
+    }
+
+    public static DatapathId of(long rawValue) {
+        return new DatapathId(rawValue);
+    }
+
+    public static DatapathId of(String s) {
+        return new DatapathId(HexString.toLong(s));
+    }
+
+    public long getLong() {
+        return rawValue;
+    }
+
+    public U64 getUnsignedLong() {
+        return U64.of(rawValue);
+    }
+
+    @Override
+    public String toString() {
+        return HexString.toHexString(rawValue);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (rawValue ^ (rawValue >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        DatapathId other = (DatapathId) obj;
+        if (rawValue != other.rawValue)
+            return false;
+        return true;
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
new file mode 100644
index 0000000..2827a72
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
@@ -0,0 +1,92 @@
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class OFBitMask128 implements OFValueType<OFBitMask128> {
+
+    static final int LENGTH = 16;
+
+    private final long raw1; // MSBs (ports 64-127)
+    private final long raw2; // LSBs (ports 0-63)
+
+    public static final OFBitMask128 ALL = new OFBitMask128(-1, -1);
+    public static final OFBitMask128 NONE = new OFBitMask128(0, 0);
+
+    private OFBitMask128(long raw1, long raw2) {
+        this.raw1 = raw1;
+        this.raw2 = raw2;
+    }
+
+    static OFBitMask128 of(long raw1, long raw2) {
+        if (raw1 == -1 && raw2 == -1)
+            return ALL;
+        if (raw1 == 0 && raw2 == 0)
+            return NONE;
+        return new OFBitMask128(raw1, raw2);
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public OFBitMask128 applyMask(OFBitMask128 mask) {
+        return of(this.raw1 & mask.raw1, this.raw2 & mask.raw2);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof OFBitMask128))
+            return false;
+        OFBitMask128 other = (OFBitMask128)obj;
+        return (other.raw1 == this.raw1 && other.raw2 == this.raw2);
+    }
+
+    @Override
+    public int hashCode() {
+        return (int)(31 * raw1 + raw2);
+    }
+
+    protected static boolean isBitOn(long raw1, long raw2, int bit) {
+        if (bit < 0 || bit >= 128)
+            throw new IndexOutOfBoundsException();
+        long word;
+        if (bit < 64) {
+            word = raw2; // ports 0-63
+        } else {
+            word = raw1; // ports 64-127
+            bit -= 64;
+        }
+        return (word & ((long)1 << bit)) != 0;
+    }
+
+    public void write16Bytes(ChannelBuffer cb) {
+        cb.writeLong(raw1);
+        cb.writeLong(raw2);
+    }
+
+    public static OFBitMask128 read16Bytes(ChannelBuffer cb) {
+        long raw1 = cb.readLong();
+        long raw2 = cb.readLong();
+        return of(raw1, raw2);
+    }
+
+    public boolean isOn(int bit) {
+        return isBitOn(raw1, raw2, bit);
+    }
+
+    @Override
+    public String toString() {
+        return (String.format("%64s", Long.toBinaryString(raw2)) + String.format("%64s", Long.toBinaryString(raw1))).replaceAll(" ", "0");
+    }
+
+    @Override
+    public int compareTo(OFBitMask128 o) {
+        long c = this.raw1 - o.raw1;
+        if (c != 0)
+            return Long.signum(c);
+        return Long.signum(this.raw2 - o.raw2);
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
index 856eff0..f541b61 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
@@ -36,14 +36,6 @@
         return Long.toString(U32.f(rawValue));
     }
 
-    public void write4Bytes(ChannelBuffer c) {
-        c.writeInt(this.rawValue);
-    }
-
-    public static OFBufferId read4Bytes(ChannelBuffer c) throws OFParseError {
-        return OFBufferId.of(c.readInt());
-    }
-
     @Override
     public int hashCode() {
         final int prime = 31;
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java
index cb36d0c..0028cd8 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java
@@ -87,12 +87,17 @@
      * output port). NOTE: OpenFlow 1.0 calls this 'NONE'
      */
     public final static OFPort ANY = new NamedPort(OFPP_ANY_INT, "any");
+    /** the wildcarded default for OpenFlow 1.0 (value: 0). Elsewhere in OpenFlow
+     *  we need "ANY" as the default
+     */
+    public static final OFPort ZERO = OFPort.of(0);
 
     public static final OFPort NO_MASK = OFPort.of(0xFFFFFFFF);
-    public static final OFPort FULL_MASK = OFPort.of(0x0);
+    public static final OFPort FULL_MASK = ZERO;
 
     /** cache of frequently used ports */
     private static class PrecachedPort {
+        private final static OFPort p0 = new OFPort(0);
         private final static OFPort p1 = new OFPort(1);
         private final static OFPort p2 = new OFPort(2);
         private final static OFPort p3 = new OFPort(3);
@@ -160,6 +165,8 @@
      */
     public static OFPort ofInt(final int portNumber) {
         switch (portNumber) {
+            case 0:
+                return PrecachedPort.p0;
             case 1:
                 return PrecachedPort.p1;
             case 2:
@@ -302,6 +309,8 @@
      */
     public static OFPort ofShort(final short portNumber) {
         switch (portNumber) {
+            case 0:
+                return PrecachedPort.p0;
             case 1:
                 return PrecachedPort.p1;
             case 2:
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortMap.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortMap.java
new file mode 100644
index 0000000..8ec056e
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortMap.java
@@ -0,0 +1,75 @@
+package org.projectfloodlight.openflow.types;
+
+
+public class OFPortMap extends Masked<OFBitMask128> {
+
+    private OFPortMap(OFBitMask128 mask) {
+        super(OFBitMask128.NONE, mask);
+    }
+
+    public boolean isOn(OFPort port) {
+        return !(this.mask.isOn(port.getPortNumber()));
+    }
+
+    public static OFPortMap ofPorts(OFPort... ports) {
+        Builder builder = new Builder();
+        for (OFPort port: ports) {
+            builder.set(port);
+        }
+        return builder.build();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof OFPortMap))
+            return false;
+        OFPortMap other = (OFPortMap)obj;
+        return (other.value.equals(this.value) && other.mask.equals(this.mask));
+    }
+
+    @Override
+    public int hashCode() {
+        return 619 * mask.hashCode() + 257 * value.hashCode();
+    }
+
+    public static class Builder {
+        private long raw1 = -1, raw2 = -1;
+
+        public Builder() {
+
+        }
+
+        public boolean isOn(OFPort port) {
+            return !(OFBitMask128.isBitOn(raw1, raw2, port.getPortNumber()));
+        }
+
+        public Builder unset(OFPort port) {
+            int bit = port.getPortNumber();
+            if (bit < 0 || bit >= 127) // MAX PORT IS 127
+                throw new IndexOutOfBoundsException("Port number is out of bounds");
+            if (bit < 64) {
+                raw2 |= ((long)1 << bit);
+            } else {
+                raw1 |= ((long)1 << (bit - 64));
+            }
+            return this;
+        }
+
+        public Builder set(OFPort port) {
+            int bit = port.getPortNumber();
+            if (bit < 0 || bit >= 127)
+                throw new IndexOutOfBoundsException("Port number is out of bounds");
+            if (bit < 64) {
+                raw2 &= ~((long)1 << bit);
+            } else {
+                raw1 &= ~((long)1 << (bit - 64));
+            }
+            return this;
+        }
+
+        public OFPortMap build() {
+            return new OFPortMap(OFBitMask128.of(raw1, raw2));
+        }
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
index d6f65d5..6bd7581 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
@@ -5,15 +5,45 @@
 
 import com.google.common.primitives.Shorts;
 
+/** Represents an OpenFlow Vlan VID, as specified by the OpenFlow 1.3 spec.
+ *
+ *  <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
+ *      the additional mask bits 0x1000 to represent the presence of a vlan
+ *      tag. This additional bit will be stripped when writing a OF1.0 value
+ *      tag.
+ *  </b>
+ *
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ *
+ */
 public class VlanVid implements OFValueType<VlanVid> {
 
-    private static final short VALIDATION_MASK = 0x0FFF;
+    private static final short VALIDATION_MASK = 0x1FFF;
+    private static final short PRESENT_VAL = 0x1000;
+    private static final short VLAN_MASK = 0x0FFF;
     private static final short NONE_VAL = 0x0000;
+    private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
+    private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
     final static int LENGTH = 2;
 
+    /** presence of a VLAN tag is idicated by the presence of bit 0x1000 */
+    public static final VlanVid PRESENT = new VlanVid(PRESENT_VAL);
+
+    /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
     public static final VlanVid NONE = new VlanVid(NONE_VAL);
+
+    /** for use with masking operations */
     public static final VlanVid NO_MASK = new VlanVid((short)0xFFFF);
-    public static final VlanVid FULL_MASK = VlanVid.of((short)0x0);
+    public static final VlanVid FULL_MASK = NONE;
+
+    /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
+    public static final VlanVid UNTAGGED = new VlanVid(NONE_VAL) {
+        @Override
+        public void write2BytesOF10(ChannelBuffer c) {
+            c.writeShort(UNTAGGED_VAL_OF10);
+        }
+    };
 
     private final short vid;
 
@@ -21,14 +51,42 @@
         this.vid = vid;
     }
 
-    public static VlanVid of(short vid) {
-        if(vid == NONE_VAL)
-            return NONE;
+    public static VlanVid ofRawVid(short vid) {
+        if(vid == UNTAGGED_VAL_OF13)
+            return UNTAGGED;
+        else if(vid == PRESENT_VAL)
+            return PRESENT;
         else if ((vid & VALIDATION_MASK) != vid)
-            throw new IllegalArgumentException("Illegal VLAN VID value: " + vid);
+            throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
         return new VlanVid(vid);
     }
 
+    public static VlanVid ofVlan(int vlan) {
+        if( (vlan & VLAN_MASK) != vlan)
+            throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
+        return ofRawVid( (short) (vlan | PRESENT_VAL));
+    }
+
+    public static VlanVid ofVlanOF10(short of10vlan) {
+        if(of10vlan == NONE_VAL) {
+            return NONE;
+        } else if(of10vlan == UNTAGGED_VAL_OF10) {
+            return UNTAGGED;
+        } else {
+            return ofVlan(of10vlan);
+        }
+    }
+
+    /** @return whether or not this VlanId has the present (0x1000) bit set */
+    public boolean isPresentBitSet() {
+       return (vid & PRESENT_VAL) != 0;
+    }
+
+    /** @return the actual VLAN tag this vid identifies */
+    public short getVlan() {
+        return (short) (vid & VLAN_MASK);
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (!(obj instanceof VlanVid))
@@ -50,10 +108,11 @@
         return "0x" + Integer.toHexString(vid);
     }
 
-    public short getValue() {
+    public short getRawVid() {
         return vid;
     }
 
+
     @Override
     public int getLength() {
         return LENGTH;
@@ -79,13 +138,21 @@
         c.writeShort(this.vid);
     }
 
+    public void write2BytesOF10(ChannelBuffer c) {
+        c.writeShort(this.getVlan());
+    }
+
     public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
-        return VlanVid.of(c.readShort());
+        return VlanVid.ofRawVid(c.readShort());
+    }
+
+    public static VlanVid read2BytesOF10(ChannelBuffer c) throws OFParseError {
+        return VlanVid.ofVlanOF10(c.readShort());
     }
 
     @Override
     public VlanVid applyMask(VlanVid mask) {
-        return VlanVid.of((short)(this.vid & mask.vid));
+        return VlanVid.ofRawVid((short)(this.vid & mask.vid));
     }
 
     @Override
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java
new file mode 100644
index 0000000..cb81d31
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java
@@ -0,0 +1,11 @@
+package org.projectfloodlight.openflow.types;
+
+public class VlanVidWithMask extends Masked<VlanVid> {
+    private VlanVidWithMask(VlanVid value, VlanVid mask) {
+        super(value, mask);
+    }
+
+    /* a combination of Vlan Vid and mask that matches any tagged packet */
+    public final static VlanVidWithMask ANY_TAGGED = new VlanVidWithMask(VlanVid.PRESENT, VlanVid.PRESENT);
+
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortMapTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortMapTest.java
new file mode 100644
index 0000000..7a75248
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortMapTest.java
@@ -0,0 +1,54 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.junit.Assert.assertArrayEquals;
+import junit.framework.TestCase;
+
+import org.junit.Test;
+
+public class OFPortMapTest extends TestCase {
+
+    @Test
+    public void testOFPortMap() {
+        Boolean[] on = new Boolean[128];
+        for (int i = 0; i < 128; i++) {
+            on[i] = false;
+        }
+
+        OFPortMap.Builder builder = new OFPortMap.Builder();
+
+        for (int i = 0; i < 128; i += 3) {
+            OFPort p = OFPort.of(i);
+            builder.set(p);
+            on[p.getPortNumber()] = true;
+        }
+
+        // Test that all ports that were added are actually on, and all other ports are off
+        OFPortMap portmap = builder.build();
+        //System.out.println(portmap);
+        Boolean[] actual = new Boolean[128];
+        for (int i = 0; i < 128; i++) {
+            actual[i] = false;
+        }
+        for (int i = 0; i < 128; i++) {
+            actual[i] = portmap.isOn(OFPort.of(i));
+        }
+        assertArrayEquals(on, actual);
+
+        // Turn some ports off
+        for (int i = 0; i < 128; i += 7) {
+            on[i] = false;
+            builder.unset(OFPort.of(i));
+        }
+
+        // Test again
+        portmap = builder.build();
+        actual = new Boolean[128];
+        for (int i = 0; i < 128; i++) {
+            actual[i] = false;
+        }
+        for (int i = 0; i < 128; i++) {
+            actual[i] = portmap.isOn(OFPort.of(i));
+        }
+        assertArrayEquals(on, actual);
+    }
+}
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index aa68d04..458d3f0 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -56,6 +56,13 @@
 //:: for prop in msg.data_members:
     private final ${prop.java_type.public_type} ${prop.name};
 //:: #endfor
+//
+//:: if all(prop.default_value for prop in msg.data_members):
+    // Immutable default instance
+    final static ${impl_class} DEFAULT = new ${impl_class}(
+        ${", ".join(prop.default_name for prop in msg.data_members)}
+    );
+//:: #endif
 
     //:: if msg.data_members:
     // package private constructor - used by readers, builders, and factory
@@ -195,27 +202,30 @@
 //:: elif prop.is_pad:
             // pad: ${prop.length} bytes
             bb.skipBytes(${prop.length});
-//:: elif prop.is_fixed_value:
-            // fixed value property ${prop.name} == ${prop.value}
-            ${prop.java_type.priv_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
-            if(${prop.name} != ${prop.priv_value})
-                throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
 //:: elif prop.is_length_value:
-            ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
+            ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True)};
+            //:: if prop.is_fixed_value:
+            if(${prop.name} != ${prop.value})
+                throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
+            //:: else:
             if(${prop.name} < MINIMUM_LENGTH)
                 throw new OFParseError("Wrong ${prop.name}: Expected to be >= " + MINIMUM_LENGTH + ", was: " + ${prop.name});
-//:: elif prop.is_field_length_value:
-//::        fields_with_length_member[prop.member.field_name] = prop.name
-            int ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
-//:: else:
-    // fixme: todo ${prop.name}
-//:: #endif
-//:: if prop.is_length_value or prop.is_field_length_value:
+            //:: #endif
             if(bb.readableBytes() + (bb.readerIndex() - start) < ${prop.name}) {
                 // Buffer does not have all data yet
                 bb.readerIndex(start);
                 return null;
             }
+//:: elif prop.is_fixed_value:
+            // fixed value property ${prop.name} == ${prop.value}
+            ${prop.java_type.priv_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
+            if(${prop.name} != ${prop.priv_value})
+                throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
+//:: elif prop.is_field_length_value:
+//::        fields_with_length_member[prop.member.field_name] = prop.name
+            ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True)};
+//:: else:
+    // fixme: todo ${prop.name}
 //:: #endif
 //:: #endfor
             //:: if msg.align:
@@ -354,6 +364,8 @@
         //:: for prop in msg.data_members:
         //:: if prop.java_type.pub_type == 'long':
         result = prime *  (int) (${prop.name} ^ (${prop.name} >>> 32));
+        //:: elif prop.java_type.pub_type == 'boolean':
+        result = prime * result + (${prop.name} ? 1231 : 1237);
         //:: elif prop.java_type.is_primitive:
         result = prime * result + ${prop.name};
         //:: elif prop.java_type.is_array:
diff --git a/java_gen/templates/of_factory_class.java b/java_gen/templates/of_factory_class.java
index 5263226..9352541 100644
--- a/java_gen/templates/of_factory_class.java
+++ b/java_gen/templates/of_factory_class.java
@@ -45,6 +45,10 @@
     private final XidGenerator xidGenerator = XidGenerators.global();
     //:: #endif
 
+    public OFVersion getOFVersion() {
+        return OFVersion.OF_${factory.version.of_version};
+    }
+
     //:: for name, clazz in factory.interface.sub_factories.items():
     public ${clazz} ${name}() {
         return ${clazz}Ver${factory.version.of_version}.INSTANCE;
@@ -72,6 +76,12 @@
     public Match.Builder buildMatch() {
         return new ${i.versioned_class(factory.version).name}.Builder();
     }
+
+    final static Match MATCH_WILDCARD_ALL = ${i.versioned_class(factory.version).name}.DEFAULT;
+
+    public Match matchWildcardAll() {
+        return MATCH_WILDCARD_ALL;
+    }
     //::     general_get_match_func_written = True
     //:: #endif
     //:: if len(i.writeable_members) <= 2:
diff --git a/java_gen/templates/of_factory_interface.java b/java_gen/templates/of_factory_interface.java
index 48ea34a..c4ec8af 100644
--- a/java_gen/templates/of_factory_interface.java
+++ b/java_gen/templates/of_factory_interface.java
@@ -55,11 +55,13 @@
 //:: #endfor
 //:: if factory.name == 'OFFactory':
     Match.Builder buildMatch();
+    Match matchWildcardAll();
 //:: #endif
 
+    OFVersion getOFVersion();
     OFMessageReader<${factory.base_class}> getReader();
-
 //:: if factory.name == 'OFOxms':
+
     public <F extends OFValueType<F>> OFOxm<F> fromValue(F value, MatchField<F> field);
     public <F extends OFValueType<F>> OFOxm<F> fromValueAndMask(F value, F mask, MatchField<F> field);
     public <F extends OFValueType<F>> OFOxm<F> fromMasked(Masked<F> masked, MatchField<F> field);
diff --git a/java_gen/templates/unit_test.java b/java_gen/templates/unit_test.java
index 47dcc24..5a525e4 100644
--- a/java_gen/templates/unit_test.java
+++ b/java_gen/templates/unit_test.java
@@ -28,6 +28,7 @@
 //:: from loxi_ir import *
 //:: import itertools
 //:: import of_g
+//:: import java_gen.java_model as java_model
 //:: include('_copyright.java')
 
 //:: include('_autogen.java')
@@ -40,22 +41,25 @@
 import static org.junit.Assert.*;
 
 public class ${test.name} {
+    //:: factory = java_model.model.factory_of(test.interface)
     //:: var_type = msg.interface.name
     //:: var_name = msg.interface.variable_name
-    OFFactory factory;
+    //:: builder_method = factory.method_name(msg.interface)
+    //:: factory_impl = java_model.model.factory_of(test.interface).of_version(test.java_class.version).name
+    ${factory.name if factory.name is not None else "OFFactory"} factory;
 
     final static byte[] ${msg.constant_name}_SERIALIZED =
         new byte[] { ${", ".join("%s0x%x" % (("" if ord(c)<128 else "(byte) "),  ord(c)) for c in test_data["binary"] ) } };
 
     @Before
     public void setup() {
-        factory = OFFactories.getFactory(OFVersion.${version.constant_version});
+        factory = ${factory_impl + ".INSTANCE" if factory_impl is not None else "OFFactories.getFactory(OFVersion." + version.constant_version + ")"};
     }
 
     //:: if "java" in test_data:
     @Test
     public void testWrite() {
-        ${var_type}.Builder builder = factory.build${var_type[2:]}();
+        ${var_type}.Builder builder = factory.${builder_method}();
         ${test_data["java"]};
         ${var_type} ${var_name} = builder.build();
         ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
@@ -68,7 +72,7 @@
 
     @Test
     public void testRead() throws Exception {
-        ${var_type}.Builder builder = factory.build${var_type[2:]}();
+        ${var_type}.Builder builder = factory.${builder_method}();
         ${test_data["java"]};
         ${var_type} ${var_name}Built = builder.build();
 
diff --git a/loxi_front_end/match.py b/loxi_front_end/match.py
index 20d5030..c510477 100644
--- a/loxi_front_end/match.py
+++ b/loxi_front_end/match.py
@@ -394,6 +394,16 @@
         takes_mask_in_spec=False,
         order=501,
         ),
+
+    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,
+        ),
 )
 
 match_keys_sorted = of_match_members.keys()
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..7111259 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
@@ -302,14 +302,15 @@
 #    of_match_v4_t = dict(bytes=-1, to_w="match_v4_hton",
 #                         from_w="match_v4_ntoh",
 #                         short_name="match_v4"),
-    of_octets_t = dict(bytes=-1, short_name="octets")
+    of_octets_t = dict(bytes=-1, short_name="octets"),
+    of_bitmap_128_t = dict(bytes=16, short_name="bitmap_128"),
 )
 
 of_scalar_types = ["char", "uint8_t", "uint16_t", "uint32_t", "uint64_t",
                    "of_port_no_t", "of_fm_cmd_t", "of_wc_bmap_t",
                    "of_match_bmap_t", "of_port_name_t", "of_table_name_t",
                    "of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
-                   "of_ipv6_t", "of_ipv4_t"]
+                   "of_ipv6_t", "of_ipv4_t", "of_bitmap_128_t"]
 
 base_object_members = """\
     /* The control block for the underlying data buffer */
diff --git a/openflow_input/bsn_in_ports b/openflow_input/bsn_in_ports
new file mode 100644
index 0000000..05003b9
--- /dev/null
+++ b/openflow_input/bsn_in_ports
@@ -0,0 +1,61 @@
+// 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.
+
+#version 3
+#version 4
+
+/*
+ * Bitmap of input ports
+ *
+ * The representation is not straightforward, but it works with existing OXM
+ * semantics.
+ *
+ * The value should always be zero. The mask should be unset in every bit position
+ * where the corresponding input port is allowed, and set in all other bits.
+ * As a special case, the highest bit in the mask is reserved for higher port
+ * numbers than can be represented in the bitmap.
+ *
+ * The value1 and value_mask1 fields contain the most significant bits. value2
+ * and value_mask2 contain the least significant bits.
+ *
+ * Pseudocode for populating value or mask:
+ *   bitmap |= in_port < 128 ? (1 << in_port) : (1 << 127)
+ */
+
+struct of_oxm_bsn_in_ports_128 : of_oxm {
+    uint32_t type_len == 0x00030020;
+    of_bitmap_128_t value;
+};
+
+struct of_oxm_bsn_in_ports_128_masked : of_oxm {
+    uint32_t type_len == 0x00030120;
+    of_bitmap_128_t value;
+    of_bitmap_128_t value_mask;
+};
diff --git a/openflow_input/bsn_pdu b/openflow_input/bsn_pdu
new file mode 100644
index 0000000..790604f
--- /dev/null
+++ b/openflow_input/bsn_pdu
@@ -0,0 +1,96 @@
+// 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.
+
+#version any
+
+// When the slot_num field has this value, the message applies
+// to all currently used slots on the switch for the given port
+enum of_bsn_pdu_slot_num_t(wire_type=uint8_t, complete=False) {
+    BSN_PDU_SLOT_NUM_ANY = 0xff
+};
+
+struct of_bsn_pdu_tx_request : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 31;
+    uint32_t tx_interval_ms;
+    of_port_no_t port_no;
+    uint8_t slot_num;
+    pad(3);
+    of_octets_t data;
+};
+
+struct of_bsn_pdu_tx_reply : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 32;
+    uint32_t status; // 0 means success
+};
+
+struct of_bsn_pdu_rx_request : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 33;
+    uint32_t timeout_ms;
+    of_port_no_t port_no;
+    uint8_t slot_num;
+    pad(3);
+    of_octets_t data;
+};
+
+struct of_bsn_pdu_rx_reply : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 34;
+    uint32_t status; // 0 means success
+};
+
+struct of_bsn_pdu_rx_timeout : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 35;
+    of_port_no_t port_no;
+    uint8_t slot_num;
+};
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 0277937..3493c6b 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -66,7 +66,7 @@
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
     OFPT_ECHO_REPLY = 3,
-    OFPT_VENDOR = 4,
+    OFPT_EXPERIMENTER = 4,
     OFPT_FEATURES_REQUEST = 5,
     OFPT_FEATURES_REPLY = 6,
     OFPT_GET_CONFIG_REQUEST = 7,
@@ -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) {
@@ -214,14 +214,14 @@
     OFPSF_REPLY_MORE = 0x1,
 };
 
-enum ofp_stats_types(wire_type=uint16_t) {
+enum ofp_stats_type(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
     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,
@@ -407,7 +407,7 @@
     uint32_t n_buffers;
     uint8_t n_tables;
     pad(3);
-    uint32_t capabilities;
+    enum ofp_capabilities capabilities;
     uint32_t actions;
     list(of_port_desc_t) ports;
 };
@@ -698,8 +698,66 @@
     uint8_t type == 1;
     uint16_t length;
     uint32_t xid;
-    uint16_t err_type;
-    uint16_t code;
+    uint16_t err_type == ?;
+};
+
+struct of_hello_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 0;
+    enum ofp_hello_failed_code code;
+    of_octets_t data;
+};
+
+struct of_bad_request_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 1;
+    enum ofp_bad_request_code code;
+    of_octets_t data;
+};
+
+struct of_bad_action_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 2;
+    enum ofp_bad_action_code code;
+    of_octets_t data;
+};
+
+struct of_flow_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 3;
+    enum ofp_flow_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_port_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 4;
+    enum ofp_port_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_queue_op_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 5;
+    enum ofp_queue_op_failed_code code;
     of_octets_t data;
 };
 
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index 4156b99..85f696f 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -386,7 +386,7 @@
     OFPSCFC_BAD_LEN = 1,
 };
 
-enum ofp_stats_types(wire_type=uint16_t) {
+enum ofp_stats_type(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -529,7 +529,7 @@
     uint32_t n_buffers;
     uint8_t n_tables;
     pad(3);
-    uint32_t capabilities;
+    enum ofp_capabilities capabilities;
     uint32_t reserved;
     list(of_port_desc_t) ports;
 };
@@ -1011,8 +1011,116 @@
     uint8_t type == 1;
     uint16_t length;
     uint32_t xid;
-    uint16_t err_type;
-    uint16_t code;
+    uint16_t err_type == ?;
+};
+
+struct of_hello_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 0;
+    enum ofp_hello_failed_code code;
+    of_octets_t data;
+};
+
+struct of_bad_request_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 1;
+    enum ofp_bad_request_code code;
+    of_octets_t data;
+};
+
+struct of_bad_action_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 2;
+    enum ofp_bad_action_code code;
+    of_octets_t data;
+};
+
+struct of_bad_instruction_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 3;
+    enum ofp_bad_instruction_code code;
+    of_octets_t data;
+};
+
+struct of_bad_match_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 4;
+    enum ofp_bad_match_code code;
+    of_octets_t data;
+};
+
+struct of_flow_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 5;
+    enum ofp_flow_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_group_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 6;
+    enum ofp_group_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_port_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 7;
+    enum ofp_port_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_table_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 8;
+    enum ofp_table_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_queue_op_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 9;
+    enum ofp_queue_op_failed_code code;
+    of_octets_t data;
+};
+
+struct of_switch_config_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 10;
+    enum ofp_switch_config_failed_code code;
     of_octets_t data;
 };
 
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 1e1922b..72568fb 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,
 };
@@ -410,7 +410,7 @@
     OFPRRFC_BAD_ROLE = 2,
 };
 
-enum ofp_stats_types(wire_type=uint16_t) {
+enum ofp_stats_type(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -569,7 +569,7 @@
     uint32_t n_buffers;
     uint8_t n_tables;
     pad(3);
-    uint32_t capabilities;
+    enum ofp_capabilities capabilities;
     uint32_t reserved;
     list(of_port_desc_t) ports;
 };
@@ -954,21 +954,139 @@
     uint8_t type == 1;
     uint16_t length;
     uint32_t xid;
-    uint16_t err_type;
-    uint16_t code;
+    uint16_t err_type == ?;
+};
+
+struct of_hello_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 0;
+    enum ofp_hello_failed_code code;
     of_octets_t data;
 };
 
-// struct of_error_experimenter_msg {
-//    uint8_t version;
-//    uint8_t type;
-//    uint16_t length;
-//    uint32_t xid;
-//    uint16_t err_type;
-//    uint16_t subtype;
-//    uint32_t experimenter;
-//    of_octets_t data;
-//};
+struct of_bad_request_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 1;
+    enum ofp_bad_request_code code;
+    of_octets_t data;
+};
+
+struct of_bad_action_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 2;
+    enum ofp_bad_action_code code;
+    of_octets_t data;
+};
+
+struct of_bad_instruction_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 3;
+    enum ofp_bad_instruction_code code;
+    of_octets_t data;
+};
+
+struct of_bad_match_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 4;
+    enum ofp_bad_match_code code;
+    of_octets_t data;
+};
+
+struct of_flow_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 5;
+    enum ofp_flow_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_group_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 6;
+    enum ofp_group_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_port_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 7;
+    enum ofp_port_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_table_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 8;
+    enum ofp_table_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_queue_op_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 9;
+    enum ofp_queue_op_failed_code code;
+    of_octets_t data;
+};
+
+struct of_switch_config_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 10;
+    enum ofp_switch_config_failed_code code;
+    of_octets_t data;
+};
+
+struct of_role_request_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 11;
+    enum ofp_role_request_failed_code code;
+    of_octets_t data;
+};
+
+struct of_experimenter_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 0xffff;
+    uint16_t subtype;
+    uint32_t experimenter;
+    of_octets_t data;
+};
 
 // STATS ENTRIES: flow, table, port, queue, group stats, group desc stats
 // FIXME: Verify disambiguation w/ length in object and entry
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index 337d16c..767594a 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -92,8 +92,8 @@
     OFPT_GROUP_MOD = 15,
     OFPT_PORT_MOD = 16,
     OFPT_TABLE_MOD = 17,
-    OFPT_MULTIPART_REQUEST = 18,
-    OFPT_MULTIPART_REPLY = 19,
+    OFPT_STATS_REQUEST = 18,
+    OFPT_STATS_REPLY = 19,
     OFPT_BARRIER_REQUEST = 20,
     OFPT_BARRIER_REPLY = 21,
     OFPT_QUEUE_GET_CONFIG_REQUEST = 22,
@@ -336,9 +336,9 @@
 enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
-    OFPBRC_BAD_MULTIPART = 2,
+    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,
 };
@@ -481,30 +481,30 @@
     OFPTFFC_EPERM = 5,
 };
 
-enum ofp_multipart_types(wire_type=uint16_t) {
-    OFPMP_DESC = 0,
-    OFPMP_FLOW = 1,
-    OFPMP_AGGREGATE = 2,
-    OFPMP_TABLE = 3,
-    OFPMP_PORT_STATS = 4,
-    OFPMP_QUEUE = 5,
-    OFPMP_GROUP = 6,
-    OFPMP_GROUP_DESC = 7,
-    OFPMP_GROUP_FEATURES = 8,
-    OFPMP_METER = 9,
-    OFPMP_METER_CONFIG = 10,
-    OFPMP_METER_FEATURES = 11,
-    OFPMP_TABLE_FEATURES = 12,
-    OFPMP_PORT_DESC = 13,
-    OFPMP_EXPERIMENTER = 0xffff,
+enum ofp_stats_type(wire_type=uint16_t) {
+    OFPST_DESC = 0,
+    OFPST_FLOW = 1,
+    OFPST_AGGREGATE = 2,
+    OFPST_TABLE = 3,
+    OFPST_PORT = 4,
+    OFPST_QUEUE = 5,
+    OFPST_GROUP = 6,
+    OFPST_GROUP_DESC = 7,
+    OFPST_GROUP_FEATURES = 8,
+    OFPST_METER = 9,
+    OFPST_METER_CONFIG = 10,
+    OFPST_METER_FEATURES = 11,
+    OFPST_TABLE_FEATURES = 12,
+    OFPST_PORT_DESC = 13,
+    OFPST_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_multipart_request_flags(wire_type=uint16_t, bitmask=True) {
-    OFPMPF_REQ_MORE = 0x1,
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+    OFPSF_REQ_MORE = 0x1,
 };
 
-enum ofp_multipart_reply_flags(wire_type=uint16_t, bitmask=True) {
-    OFPMPF_REPLY_MORE = 0x1,
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
+    OFPSF_REPLY_MORE = 0x1,
 };
 
 enum ofp_table_feature_prop_type(wire_type=uint16_t) {
@@ -695,7 +695,7 @@
     uint8_t n_tables;
     uint8_t auxiliary_id;
     pad(2);
-    uint32_t capabilities;
+    enum ofp_capabilities capabilities;
     uint32_t reserved;
 };
 
@@ -1150,21 +1150,159 @@
     uint8_t type == 1;
     uint16_t length;
     uint32_t xid;
-    uint16_t err_type;
-    uint16_t code;
+    uint16_t err_type == ?;
+};
+
+struct of_hello_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 0;
+    enum ofp_hello_failed_code code;
     of_octets_t data;
 };
 
-//struct of_error_experimenter_msg {
-//    uint8_t version;
-//    uint8_t type;
-//    uint16_t length;
-//    uint32_t xid;
-//    uint16_t err_type;
-//    uint16_t subtype;
-//    uint32_t experimenter;
-//    of_octets_t data;
-//};
+struct of_bad_request_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 1;
+    enum ofp_bad_request_code code;
+    of_octets_t data;
+};
+
+struct of_bad_action_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 2;
+    enum ofp_bad_action_code code;
+    of_octets_t data;
+};
+
+struct of_bad_instruction_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 3;
+    enum ofp_bad_instruction_code code;
+    of_octets_t data;
+};
+
+struct of_bad_match_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 4;
+    enum ofp_bad_match_code code;
+    of_octets_t data;
+};
+
+struct of_flow_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 5;
+    enum ofp_flow_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_group_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 6;
+    enum ofp_group_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_port_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 7;
+    enum ofp_port_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_table_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 8;
+    enum ofp_table_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_queue_op_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 9;
+    enum ofp_queue_op_failed_code code;
+    of_octets_t data;
+};
+
+struct of_switch_config_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 10;
+    enum ofp_switch_config_failed_code code;
+    of_octets_t data;
+};
+
+struct of_role_request_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 11;
+    enum ofp_role_request_failed_code code;
+    of_octets_t data;
+};
+
+struct of_meter_mod_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 12;
+    enum ofp_meter_mod_failed_code code;
+    of_octets_t data;
+};
+
+struct of_table_features_failed_error_msg : of_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 13;
+    enum ofp_table_features_failed_code code;
+    of_octets_t data;
+};
+
+struct of_experimenter_error_msg {
+    uint8_t version;
+    uint8_t type == 1;
+    uint16_t length;
+    uint32_t xid;
+    uint16_t err_type == 0xffff;
+    uint16_t subtype;
+    uint32_t experimenter;
+    of_octets_t data;
+};
 
 // STATS ENTRIES: flow, table, port, queue, group stats, group desc stats
 
@@ -1770,7 +1908,7 @@
     list(of_meter_band_t) entries;
 };
 
-struct of_experimenter_multipart_header {
+struct of_experimenter_stats_header {
     uint32_t experimenter == ?;
     uint32_t subtype;
 };
diff --git a/py_gen/oftype.py b/py_gen/oftype.py
index a6620ab..c378cea 100644
--- a/py_gen/oftype.py
+++ b/py_gen/oftype.py
@@ -101,6 +101,11 @@
         pack='%s',
         unpack='str(%s.read_all())'),
 
+    'of_bitmap_128_t': OFTypeData(
+        init='set()',
+        pack='util.pack_bitmap_128(%s)',
+        unpack="util.unpack_bitmap_128(%s)"),
+
     # HACK need the match_v3 length field
     'list(of_oxm_t)': OFTypeData(
         init='[]',
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")
diff --git a/py_gen/templates/message.py b/py_gen/templates/message.py
index 4ec8c46..c8e31c9 100644
--- a/py_gen/templates/message.py
+++ b/py_gen/templates/message.py
@@ -122,6 +122,15 @@
     else:
         raise loxi.ProtocolError("unexpected message type")
 
+def parse_error(buf):
+    if len(buf) < 8 + 2:
+        raise loxi.ProtocolError("message too short")
+    err_type, = struct.unpack_from("!H", buf, 8)
+    if err_type in error_msg_parsers:
+        return error_msg_parsers[err_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected error type %u" % err_type)
+
 def parse_flow_mod(buf):
 :: if version == 1:
 :: offset = 57
@@ -137,7 +146,6 @@
     else:
         raise loxi.ProtocolError("unexpected flow mod cmd %u" % cmd)
 
-:: if version < of_g.VERSION_1_3:
 def parse_stats_reply(buf):
     if len(buf) < 8 + 2:
         raise loxi.ProtocolError("message too short")
@@ -155,31 +163,8 @@
         return stats_request_parsers[stats_type](buf)
     else:
         raise loxi.ProtocolError("unexpected stats type %u" % stats_type)
-:: else:
-def parse_multipart_reply(buf):
-    if len(buf) < 8 + 2:
-        raise loxi.ProtocolError("message too short")
-    multipart_type, = struct.unpack_from("!H", buf, 8)
-    if multipart_type in multipart_reply_parsers:
-        return multipart_reply_parsers[multipart_type](buf)
-    else:
-        raise loxi.ProtocolError("unexpected multipart type %u" % multipart_type)
 
-def parse_multipart_request(buf):
-    if len(buf) < 8 + 2:
-        raise loxi.ProtocolError("message too short")
-    multipart_type, = struct.unpack_from("!H", buf, 8)
-    if multipart_type in multipart_request_parsers:
-        return multipart_request_parsers[multipart_type](buf)
-    else:
-        raise loxi.ProtocolError("unexpected multipart type %u" % multipart_type)
-:: #endif
-
-:: if version == of_g.VERSION_1_0:
-def parse_vendor(buf):
-:: else:
 def parse_experimenter(buf):
-:: #endif
     if len(buf) < 16:
         raise loxi.ProtocolError("experimenter message too short")
 
@@ -210,6 +195,30 @@
 :: #endfor
 }
 
+error_msg_parsers = {
+    const.OFPET_HELLO_FAILED : hello_failed_error_msg.unpack,
+    const.OFPET_BAD_REQUEST : bad_request_error_msg.unpack,
+    const.OFPET_BAD_ACTION : bad_action_error_msg.unpack,
+    const.OFPET_FLOW_MOD_FAILED : flow_mod_failed_error_msg.unpack,
+    const.OFPET_PORT_MOD_FAILED : port_mod_failed_error_msg.unpack,
+    const.OFPET_QUEUE_OP_FAILED : queue_op_failed_error_msg.unpack,
+:: if version >= of_g.VERSION_1_1:
+    const.OFPET_BAD_INSTRUCTION : bad_instruction_error_msg.unpack,
+    const.OFPET_BAD_MATCH : bad_match_error_msg.unpack,
+    const.OFPET_GROUP_MOD_FAILED : group_mod_failed_error_msg.unpack,
+    const.OFPET_TABLE_MOD_FAILED : table_mod_failed_error_msg.unpack,
+    const.OFPET_SWITCH_CONFIG_FAILED : switch_config_failed_error_msg.unpack,
+:: #endif
+:: if version >= of_g.VERSION_1_2:
+    const.OFPET_ROLE_REQUEST_FAILED : role_request_failed_error_msg.unpack,
+    const.OFPET_EXPERIMENTER : experimenter_error_msg.unpack,
+:: #endif
+:: if version >= of_g.VERSION_1_3:
+    const.OFPET_METER_MOD_FAILED : meter_mod_failed_error_msg.unpack,
+    const.OFPET_TABLE_FEATURES_FAILED : table_features_failed_error_msg.unpack,
+:: #endif
+}
+
 flow_mod_parsers = {
     const.OFPFC_ADD : flow_add.unpack,
     const.OFPFC_MODIFY : flow_modify.unpack,
@@ -218,7 +227,6 @@
     const.OFPFC_DELETE_STRICT : flow_delete_strict.unpack,
 }
 
-:: if version < of_g.VERSION_1_3:
 stats_reply_parsers = {
     const.OFPST_DESC : desc_stats_reply.unpack,
     const.OFPST_FLOW : flow_stats_reply.unpack,
@@ -233,6 +241,13 @@
 :: if version >= of_g.VERSION_1_2:
     const.OFPST_GROUP_FEATURES : group_features_stats_reply.unpack,
 :: #endif
+:: if version >= of_g.VERSION_1_3:
+    const.OFPST_METER : meter_stats_reply.unpack,
+    const.OFPST_METER_CONFIG : meter_config_stats_reply.unpack,
+    const.OFPST_METER_FEATURES : meter_features_stats_reply.unpack,
+    const.OFPST_TABLE_FEATURES : table_features_stats_reply.unpack,
+    const.OFPST_PORT_DESC : port_desc_stats_reply.unpack,
+:: #endif
 }
 
 stats_request_parsers = {
@@ -249,42 +264,14 @@
 :: if version >= of_g.VERSION_1_2:
     const.OFPST_GROUP_FEATURES : group_features_stats_request.unpack,
 :: #endif
-}
-:: else:
-multipart_reply_parsers = {
-    const.OFPMP_DESC : desc_stats_reply.unpack,
-    const.OFPMP_FLOW : flow_stats_reply.unpack,
-    const.OFPMP_AGGREGATE : aggregate_stats_reply.unpack,
-    const.OFPMP_TABLE : table_stats_reply.unpack,
-    const.OFPMP_PORT_STATS : port_stats_reply.unpack,
-    const.OFPMP_QUEUE : queue_stats_reply.unpack,
-    const.OFPMP_GROUP : group_stats_reply.unpack,
-    const.OFPMP_GROUP_DESC : group_desc_stats_reply.unpack,
-    const.OFPMP_GROUP_FEATURES : group_features_stats_reply.unpack,
-    const.OFPMP_METER : meter_stats_reply.unpack,
-    const.OFPMP_METER_CONFIG : meter_config_stats_reply.unpack,
-    const.OFPMP_METER_FEATURES : meter_features_stats_reply.unpack,
-    const.OFPMP_TABLE_FEATURES : table_features_stats_reply.unpack,
-    const.OFPMP_PORT_DESC : port_desc_stats_reply.unpack,
-}
-
-multipart_request_parsers = {
-    const.OFPMP_DESC : desc_stats_request.unpack,
-    const.OFPMP_FLOW : flow_stats_request.unpack,
-    const.OFPMP_AGGREGATE : aggregate_stats_request.unpack,
-    const.OFPMP_TABLE : table_stats_request.unpack,
-    const.OFPMP_PORT_STATS : port_stats_request.unpack,
-    const.OFPMP_QUEUE : queue_stats_request.unpack,
-    const.OFPMP_GROUP : group_stats_request.unpack,
-    const.OFPMP_GROUP_DESC : group_desc_stats_request.unpack,
-    const.OFPMP_GROUP_FEATURES : group_features_stats_request.unpack,
-    const.OFPMP_METER : meter_stats_request.unpack,
-    const.OFPMP_METER_CONFIG : meter_config_stats_request.unpack,
-    const.OFPMP_METER_FEATURES : meter_features_stats_request.unpack,
-    const.OFPMP_TABLE_FEATURES : table_features_stats_request.unpack,
-    const.OFPMP_PORT_DESC : port_desc_stats_request.unpack,
-}
+:: if version >= of_g.VERSION_1_3:
+    const.OFPST_METER : meter_stats_request.unpack,
+    const.OFPST_METER_CONFIG : meter_config_stats_request.unpack,
+    const.OFPST_METER_FEATURES : meter_features_stats_request.unpack,
+    const.OFPST_TABLE_FEATURES : table_features_stats_request.unpack,
+    const.OFPST_PORT_DESC : port_desc_stats_request.unpack,
 :: #endif
+}
 
 :: experimenter_ofclasses = [x for x in ofclasses if x.type_members[1].value == 4]
 :: sort_key = lambda x: x.type_members[2].value
diff --git a/py_gen/templates/util.py b/py_gen/templates/util.py
index c4de5a3..1566e82 100644
--- a/py_gen/templates/util.py
+++ b/py_gen/templates/util.py
@@ -142,3 +142,23 @@
 
 def pack_list(values):
     return "".join([x.pack() for x in values])
+
+MASK64 = (1 << 64) - 1
+
+def pack_bitmap_128(value):
+    x = 0l
+    for y in value:
+        x |= 1 << y
+    return struct.pack("!QQ", (x >> 64) & MASK64, x & MASK64)
+
+def unpack_bitmap_128(reader):
+    hi, lo = reader.read("!QQ")
+    x = (hi << 64) | lo
+    i = 0
+    value = set()
+    while x != 0:
+        if x & 1 == 1:
+            value.add(i)
+        i += 1
+        x >>= 1
+    return value
diff --git a/test_data/of13/bad_match_error_msg.data b/test_data/of13/bad_match_error_msg.data
new file mode 100644
index 0000000..80a925b
--- /dev/null
+++ b/test_data/of13/bad_match_error_msg.data
@@ -0,0 +1,22 @@
+-- binary
+04 01 # version / type
+00 0f # length
+12 34 56 78 # xid
+00 04 # err_type
+00 08 # code
+61 62 63 # data
+-- python
+ofp.message.bad_match_error_msg(
+    xid=0x12345678,
+    code=ofp.OFPBMC_BAD_MASK,
+    data="abc")
+-- c
+obj = of_bad_match_error_msg_new(OF_VERSION_1_3);
+of_bad_match_error_msg_xid_set(obj, 0x12345678);
+of_bad_match_error_msg_code_set(obj, OF_MATCH_FAILED_BAD_MASK_BY_VERSION(OF_VERSION_1_3));
+of_octets_t data = { .bytes=3, .data=(uint8_t *)"\x61\x62\x63" };
+of_bad_match_error_msg_data_set(obj, &data);
+-- java
+builder.setXid(0x12345678)
+    .setCode(OFBadMatchCode.BAD_MASK)
+    .setData(new byte[] { 0x61, 0x62, 0x63 });
diff --git a/test_data/of13/bad_request_error_msg.data b/test_data/of13/bad_request_error_msg.data
new file mode 100644
index 0000000..cc2c139
--- /dev/null
+++ b/test_data/of13/bad_request_error_msg.data
@@ -0,0 +1,22 @@
+-- binary
+04 01 # version / type
+00 0f # length
+12 34 56 78 # xid
+00 01 # err_type
+00 08 # code
+61 62 63 # data
+-- python
+ofp.message.bad_request_error_msg(
+    xid=0x12345678,
+    code=ofp.OFPBRC_BUFFER_UNKNOWN,
+    data="abc")
+-- c
+obj = of_bad_request_error_msg_new(OF_VERSION_1_3);
+of_bad_request_error_msg_xid_set(obj, 0x12345678);
+of_bad_request_error_msg_code_set(obj, OF_REQUEST_FAILED_BUFFER_UNKNOWN_BY_VERSION(OF_VERSION_1_3));
+of_octets_t data = { .bytes=3, .data=(uint8_t *)"\x61\x62\x63" };
+of_bad_request_error_msg_data_set(obj, &data);
+-- java
+builder.setXid(0x12345678)
+    .setCode(OFBadRequestCode.BUFFER_UNKNOWN)
+    .setData(new byte[] { 0x61, 0x62, 0x63 });
diff --git a/test_data/of13/error.data b/test_data/of13/error.data
deleted file mode 100644
index fcb0c1c..0000000
--- a/test_data/of13/error.data
+++ /dev/null
@@ -1,13 +0,0 @@
--- binary
-04 01 # version / type
-00 0f # length
-12 34 56 78 # xid
-00 04 # err_type
-00 08 # code
-61 62 63 # data
--- python
-ofp.message.error_msg(
-    xid=0x12345678,
-    err_type=ofp.OFPET_BAD_MATCH,
-    code=ofp.OFPBMC_BAD_MASK,
-    data="abc")
diff --git a/test_data/of13/oxm_bsn_in_ports_masked_128.data b/test_data/of13/oxm_bsn_in_ports_masked_128.data
new file mode 100644
index 0000000..9ef5245
--- /dev/null
+++ b/test_data/of13/oxm_bsn_in_ports_masked_128.data
@@ -0,0 +1,24 @@
+-- binary
+00 03 # class
+01 # type/masked
+20 # length
+00 00 00 00 00 00 00 00 # value
+00 00 00 00 00 00 00 00 # ...
+ff ff ff fe ff ff ff ff # mask - Only ports 0, 17, 96 are selected (and thus are zero)
+ff ff ff ff ff fd ff fe # ...
+-- python
+ofp.oxm.bsn_in_ports_128_masked(set(), set(range(0,128)) - set((0, 17,96)))
+-- c
+obj = of_oxm_bsn_in_ports_128_masked_new(OF_VERSION_1_3);
+{
+    of_bitmap_128_t bmap = { 0, 0 };
+    of_oxm_bsn_in_ports_128_masked_value_set(obj, bmap);
+}
+{
+    of_bitmap_128_t bmap = { 0xfffffffeffffffff , 0xfffffffffffdfffe };
+    of_oxm_bsn_in_ports_128_masked_value_mask_set(obj, bmap);
+}
+-- java
+OFPortMap portmap = OFPortMap.ofPorts(OFPort.of(0), OFPort.of(17), OFPort.of(96));
+builder.setValue(portmap.getValue());
+builder.setMask(portmap.getMask());