Merge branch 'master' of github.com:floodlight/loxigen
diff --git a/Makefile b/Makefile
index 401b2f1..dbaf08b 100644
--- a/Makefile
+++ b/Makefile
@@ -84,6 +84,12 @@
 	# Unfortunately, mvn eclipse:eclipse resolves the symlink, which doesn't work with eclipse
 	cd ${OPENFLOWJ_WORKSPACE} && perl -pi -e 's{<classpathentry kind="src" path="[^"]*/java_gen/pre-written/src/}{<classpathentry kind="src" path="src/}' .classpath
 
+wireshark: .loxi_ts.wireshark
+
+.loxi_ts.wireshark: ${LOXI_PY_FILES} ${LOXI_TEMPLATE_FILES} ${INPUT_FILES}
+	./loxigen.py --install-dir=${LOXI_OUTPUT_DIR} --lang=wireshark
+	touch $@
+
 clean:
 	rm -rf loxi_output # only delete generated files in the default directory
 	rm -f loxigen.log loxigen-test.log .loxi_ts.c .loxi_ts.python .loxi_ts.java
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..4001612 100644
--- a/c_gen/c_match.py
+++ b/c_gen/c_match.py
@@ -286,6 +286,14 @@
     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,
+    OF_OXM_INDEX_BSN_LAG_ID = 37,
+    OF_OXM_INDEX_BSN_VRF = 38,
+    OF_OXM_INDEX_BSN_GLOBAL_VRF_ALLOWED = 39,
+    OF_OXM_INDEX_BSN_L3_INTERFACE_CLASS_ID = 40,
+    OF_OXM_INDEX_BSN_L3_SRC_CLASS_ID = 41,
+    OF_OXM_INDEX_BSN_L3_DST_CLASS_ID = 42,
 };
 
 #define OF_OXM_BIT(index) (((uint64_t) 1) << (index))
@@ -600,8 +608,8 @@
 
     /* For each active member, add an OXM entry to the list */
 """)
-    # @fixme Would like to generate the list in some reasonable order
-    for key, entry in match.of_match_members.items():
+    for key in match.match_keys_sorted:
+        entry = match.of_match_members[key]
         out.write("""\
     if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(src)) {
         if (!OF_MATCH_MASK_%(ku)s_EXACT_TEST(src)) {
@@ -1066,6 +1074,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 +1153,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 +1210,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..8883193 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -67,11 +67,16 @@
                 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)],
                            comma, cls))
-            elif (cls, version) in type_maps.type_val:
+            elif (cls, version) in type_maps.type_val and \
+                    type_maps.type_val[(cls, version)] != type_maps.invalid_type:
                 out.write("    %d%s /* %s */\n" %
                           (type_maps.type_val[(cls, version)], comma, cls))
             elif type_maps.message_is_extension(cls, version):
@@ -230,6 +235,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 +392,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 +501,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 +548,76 @@
         }
     }
 
+    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;
+        case 0x02: return OF_OXM_BSN_LAG_ID;
+        case 0x03: return OF_OXM_BSN_LAG_ID_MASKED;
+        case 0x04: return OF_OXM_BSN_VRF;
+        case 0x05: return OF_OXM_BSN_VRF_MASKED;
+        case 0x06: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED;
+        case 0x07: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED;
+        case 0x08: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID;
+        case 0x09: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED;
+        case 0x0a: return OF_OXM_BSN_L3_SRC_CLASS_ID;
+        case 0x0b: return OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED;
+        case 0x0c: return OF_OXM_BSN_L3_DST_CLASS_ID;
+        case 0x0d: return OF_OXM_BSN_L3_DST_CLASS_ID_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 +668,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 +843,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 +1048,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 +1165,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..f4d3f92 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,17 @@
 #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)
+#define LOCI_SHOW_u32_bsn_lag_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u32_bsn_vrf(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u8_bsn_global_vrf_allowed(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
+#define LOCI_SHOW_u32_bsn_l3_interface_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u32_bsn_l3_src_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u32_bsn_l3_dst_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
 
 #endif /* _LOCI_SHOW_H_ */
diff --git a/c_gen/templates/locitest/Makefile b/c_gen/templates/locitest/Makefile
index ed4ba13..a7a6f37 100644
--- a/c_gen/templates/locitest/Makefile
+++ b/c_gen/templates/locitest/Makefile
@@ -10,3 +10,6 @@
 
 locitest: $(OBJS)
 	$(CC) $^ -o $@
+
+# BSN build system magic
+MODULE := locitest
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..fabd25f 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,57 @@
 
     /* 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;
+    case OF_OXM_BSN_LAG_ID:
+        type_len = 0x00030200 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_LAG_ID_MASKED:
+        type_len = 0x00030300 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_VRF:
+        type_len = 0x00030400 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_VRF_MASKED:
+        type_len = 0x00030500 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_GLOBAL_VRF_ALLOWED:
+        type_len = 0x00030600 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED:
+        type_len = 0x00030700 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_L3_INTERFACE_CLASS_ID:
+        type_len = 0x00030800 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED:
+        type_len = 0x00030900 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_L3_SRC_CLASS_ID:
+        type_len = 0x00030a00 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED:
+        type_len = 0x00030b00 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_L3_DST_CLASS_ID:
+        type_len = 0x00030c00 | (type_len & 0xff);
+        break;
+    case OF_OXM_BSN_L3_DST_CLASS_ID_MASKED:
+        type_len = 0x00030d00 | (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..4369b30 100644
--- a/java_gen/codegen.py
+++ b/java_gen/codegen.py
@@ -44,20 +44,20 @@
 import java_gen.java_model as java_model
 
 def gen_all_java(out, name):
+    # close the virtual file - we don't need it
+    out.close()
     basedir= '%s/openflowj' % of_g.options.install_dir
     print "Outputting to %s" % basedir
     if os.path.exists(basedir):
         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()
     gen.create_of_const_enums()
     gen.create_of_factories()
 
-    out.close()
 
 
 class JavaGenerator(object):
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 410a1dd..85a6c0d 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", "OFGroup"))
     # 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,21 @@
                 "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),
+                "OFOxmBsnLagId":            OxmMapEntry("LagId", "BSN_LAG_ID", False),
+                "OFOxmBsnLagIdMasked":      OxmMapEntry("LagId", "BSN_LAG_ID", True),
+                "OFOxmBsnVrf":              OxmMapEntry("VRF", "BSN_VRF", False),
+                "OFOxmBsnVrfMasked":        OxmMapEntry("VRF", "BSN_VRF", True),
+                "OFOxmBsnGlobalVrfAllowed":          OxmMapEntry("OFBooleanValue", "BSN_GLOBAL_VRF_ALLOWED", False),
+                "OFOxmBsnGlobalVrfAllowedMasked":    OxmMapEntry("OFBooleanValue", "BSN_GLOBAL_VRF_ALLOWED", True),
+                "OFOxmBsnL3InterfaceClassId":        OxmMapEntry("ClassId", "BSN_L3_INTERFACE_CLASS_ID", False),
+                "OFOxmBsnL3InterfaceClassIdMasked":  OxmMapEntry("ClassId", "BSN_L3_INTERFACE_CLASS_ID", True),
+                "OFOxmBsnL3SrcClassId":              OxmMapEntry("ClassId", "BSN_L3_SRC_CLASS_ID", False),
+                "OFOxmBsnL3SrcClassIdMasked":        OxmMapEntry("ClassId", "BSN_L3_SRC_CLASS_ID", True),
+                "OFOxmBsnL3DstClassId":              OxmMapEntry("ClassId", "BSN_L3_DST_CLASS_ID", False),
+                "OFOxmBsnL3DstClassIdMasked":        OxmMapEntry("ClassId", "BSN_L3_DST_CLASS_ID", True),
                 }
 
     # Registry of nullable properties:
@@ -299,7 +222,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 +321,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 +370,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 +514,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":
@@ -617,6 +554,8 @@
             return ("queueprop", "OFQueueProp", None)
         elif loxi_utils.class_is_hello_elem(self.c_name):
             return ("", "OFHelloElem", None)
+        elif loxi_utils.class_is_table_feature_prop(self.c_name):
+            return ("", "OFTableFeatureProp", None)
         else:
             return ("", None, None)
 
@@ -656,29 +595,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 +731,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)
@@ -840,6 +785,10 @@
         return int(self.ir_class.params['align']) if 'align' in self.ir_class.params else 0
 
     @property
+    def length_includes_align(self):
+        return self.ir_class.params['length_includes_align'] == "True" if 'length_includes_align' in self.ir_class.params else False
+
+    @property
     @memoize
     def superclass(self):
         return find(lambda c: c.version == self.version and c.c_name == self.ir_class.superclass, model.all_classes)
@@ -962,9 +911,9 @@
     @property
     def priv_value(self):
         if self.name == "version":
-            return self.msg.version.int_version
+            return self.java_type.format_value(self.msg.version.int_version, pub_type=False)
         elif self.name == "length" or self.name == "len":
-            return self.msg.length
+            return self.java_type.format_value(self.msg.length, pub_type=False)
         else:
             return self.java_type.format_value(self.member.value, pub_type=False)
 
@@ -993,6 +942,8 @@
                 name = 'length'
             elif member.name == 'value_mask':
                 name = 'mask'
+            elif member.name == 'group_id':
+                name = 'group'
             else:
                 name = java_type.name_c_to_camel(member.name)
             j_type = java_type.convert_to_jtype(java_class.c_name, member.name, member.oftype)
@@ -1066,16 +1017,23 @@
         self.java_class = java_class
         first_data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
                                                      name=java_class.c_name[3:])
-        data_file_template = "of{version}/{name}.".format(version=java_class.version.of_version,
-                                                     name=java_class.c_name[3:]) + "{i}.data"
+        glob_file_name = "of{version}/{name}__*.data".format(version=java_class.version.of_version,
+                                                     name=java_class.c_name[3:])
         test_class_name = self.java_class.name + "Test"
         self.test_units = []
         if test_data.exists(first_data_file_name):
             self.test_units.append(JavaUnitTest(java_class, first_data_file_name, test_class_name))
+
         i = 1
-        while test_data.exists(data_file_template.format(i=i)):
-            self.test_units.append(JavaUnitTest(java_class, data_file_template.format(i=i), test_class_name + str(i)))
-            i = i + 1
+        for f in test_data.glob(glob_file_name):
+            m = re.match(".*__(.*).data", f)
+            if m:
+                suffix = java_type.name_c_to_caps_camel(m.group(1))
+            else:
+                suffix = str(i)
+                i += 1
+            test_class_name = self.java_class.name + suffix + "Test"
+            self.test_units.append(JavaUnitTest(java_class, f, test_class_name))
 
     @property
     def package(self):
@@ -1113,7 +1071,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 +1094,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..2772a86 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -33,25 +33,26 @@
     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 = {
-        'byte' : (True, 8),
-        'char' : (False, 16),
-        'short' : (True, 16),
-        'int' : (True, 32),
-        'long' : (True, 64),
+        'boolean' : (False, 8, False),
+        'byte' : (True, 8, True),
+        'char' : (False, 16, True),
+        'short' : (True, 16, True),
+        'int' : (True, 32, False),
+        'long' : (True, 64, False),
 }
 
 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]
+    signed, bits, cast_needed = java_primitives_info[t]
     max = (1 << bits)-1
     if value > max:
         raise Exception("Value %d to large for type %s" % (value, t))
@@ -64,20 +65,21 @@
                 return str((1 << bits) - value)
             else:
                 return "(%s) 0x%x" % (t, value)
-        else:
-            return "0x%x%s" % (value, "L" if t=="long" else "")
+    return "%s0x%x%s" % ("(%s) " % t if cast_needed else "", value, "L" if t=="long" else "")
+
 
 ANY = 0xFFFFFFFFFFFFFFFF
 
 class VersionOp:
-    def __init__(self, version=ANY, read=None, write=None, default=None):
+    def __init__(self, version=ANY, read=None, write=None, default=None, funnel=None):
         self.version = version
         self.read = read
         self.write = write
         self.default = default
+        self.funnel = funnel
 
     def __str__(self):
-        return "[Version: %d, Read: '%s', Write: '%s', Default: '%s' ]" % (self.version, self.read, self.write, self.default )
+        return "[Version: %d, Read: '%s', Write: '%s', Default: '%s', Funnel: '%s' ]" % (self.version, self.read, self.write, self.default, self.funnel )
 
 ### FIXME: This class should really be cleaned up
 class JType(object):
@@ -93,7 +95,11 @@
         self.priv_type = priv_type  # the internal storage type
         self.ops = {}
 
-    def op(self, version=ANY, read=None, write=None, default=None, pub_type=ANY):
+    def set_priv_type(self, priv_type):
+        self.priv_type = priv_type
+        return self
+
+    def op(self, version=ANY, read=None, write=None, default=None, funnel=None, pub_type=ANY):
         """
         define operations to be performed for reading and writing this type
         (when read_op, write_op is called). The operations 'read' and 'write'
@@ -109,7 +115,7 @@
 
         pub_types = [ pub_type ] if pub_type is not ANY else [ False, True ]
         for pub_type in pub_types:
-            self.ops[(version, pub_type)] = VersionOp(version, read, write, default)
+            self.ops[(version, pub_type)] = VersionOp(version, read, write, default, funnel)
         return self
 
     def format_value(self, value, pub_type=True):
@@ -135,6 +141,24 @@
         """ Is the private type different from the public one?"""
         return self.pub_type != self.priv_type
 
+    def get_op(self, op_type, version, pub_type, default_value, arguments):
+        ver = ANY if version is None else version.int_version
+
+        if not "version" in arguments:
+            arguments["version"] = version.of_version
+
+        def lookup(ver, pub_type):
+            if (ver, pub_type) in self.ops:
+                return getattr(self.ops[(ver, pub_type)], op_type)
+            else:
+                return None
+
+        _op = lookup(ver, pub_type) or lookup(ANY, pub_type) or default_value
+        if callable(_op):
+            return _op(**arguments)
+        else:
+            return reduce(lambda a,repl: a.replace("$%s" % repl[0], str(repl[1])),  arguments.items(), _op)
+
     def read_op(self, version=None, length=None, pub_type=True):
         """ return a Java stanza that reads a value of this JType from ChannelBuffer bb.
         @param version int - OF wire version to generate expression for
@@ -148,20 +172,12 @@
              # assumes that
              # (1) length of the message has been read to 'length'
              # (2) readerIndex at the start of the message has been stored in 'start'
-            length = "length - (bb.readerIndex() - start)";
+            length = "length - (bb.readerIndex() - start)"
 
-        ver = ANY if version is None else version.int_version
-        _read_op = None
-        if (ver, pub_type) in self.ops:
-            _read_op = self.ops[(ver, pub_type)].read or self.ops[(ANY, pub_type)].read
-        elif (ANY, pub_type) in self.ops:
-            _read_op = self.ops[(ANY, pub_type)].read
-        if _read_op is None:
-            _read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type
-        if callable(_read_op):
-            return _read_op(version)
-        else:
-            return _read_op.replace("$length", str(length)).replace("$version", version.of_version)
+        return self.get_op("read", version, pub_type,
+            default_value='ChannelUtilsVer$version.read%s(bb)' % self.pub_type,
+            arguments=dict(length=length)
+            )
 
     def write_op(self, version=None, name=None, pub_type=True):
         """ return a Java stanza that writes a value of this JType contained in Java expression
@@ -171,37 +187,22 @@
         @param pub_type boolean use this JTypes 'public' (True), or private (False) representation
         @return string containing generated Java expression.
         """
-        ver = ANY if version is None else version.int_version
-        _write_op = None
-        if (ver, pub_type) in self.ops:
-            _write_op = self.ops[(ver, pub_type)].write or self.ops[(ANY, pub_type)].write
-        elif (ANY, pub_type) in self.ops:
-            _write_op = self.ops[(ANY, pub_type)].write
-        if _write_op is None:
 
-            _write_op = 'ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type
-        if callable(_write_op):
-            return _write_op(version, name)
-        else:
-            return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
+        return self.get_op("write", version, pub_type,
+            default_value='ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type,
+            arguments=dict(name=name)
+            )
+
 
     def default_op(self, version=None, pub_type=True):
         """ return a Java stanza that returns a default value of this JType.
         @param version JavaOFVersion
         @return string containing generated Java expression.
         """
-        ver = ANY if version is None else version.int_version
-        _default_op = None
-        if (ver, pub_type) in self.ops:
-            _default_op = self.ops[(ver, pub_type)].default or self.ops[(ANY, pub_type)].default
-        elif (ANY, pub_type) in self.ops:
-            _default_op = self.ops[(ANY, pub_type)].default
-        if _default_op is None:
-            _default_op = self.format_value(0) if self.is_primitive else "null"
-        if callable(_default_op):
-            return _default_op(version, name)
-        else:
-            return _default_op.replace("$version", version.of_version)
+        return self.get_op("default", version, pub_type,
+            arguments = dict(),
+            default_value = self.format_value(0) if self.is_primitive else "null"
+        )
 
     def skip_op(self, version=None, length=None):
         """ return a java stanza that skips an instance of JType in the input ChannelBuffer 'bb'.
@@ -210,26 +211,81 @@
             Currently just delegates to read_op + throws away the result."""
         return self.read_op(version, length)
 
+    def funnel_op(self, version=None, name=None, pub_type=True):
+        t = self.pub_type if pub_type else self.priv_type
+        return self.get_op("funnel", version, pub_type,
+            arguments = dict(name=name),
+            default_value =  '$name.putTo(sink)' if not self._is_primitive(pub_type) else "sink.put{}($name)".format(t[0].upper() + t[1:])
+        )
+
     @property
     def is_primitive(self):
+        return self._is_primitive()
+
+    def _is_primitive(self, pub_type=True):
         """ return true if the pub_type is a java primitive type (and thus needs
         special treatment, because it doesn't have methods)"""
-        return self.pub_type in java_primitive_types
+        t = self.pub_type if pub_type else self.priv_type
+        return t in java_primitive_types
 
     @property
     def is_array(self):
-        """ return true iff the pub_type is a Java array (and thus requires special
-        treatment for equals / toString etc.) """
-        return self.pub_type.endswith("[]")
+        return self._is_array()
 
+    def _is_array(self, pub_type=True):
+        t = self.pub_type if pub_type else self.priv_type
+        return t.endswith("[]")
+
+# Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}>
+def gen_enum_jtype(java_name, is_bitmask=False):
+    if is_bitmask:
+        java_type = "Set<{}>".format(java_name)
+        default_value = "ImmutableSet.<{}>of()".format(java_name)
+    else:
+        java_type = java_name
+        default_value = "null"
+
+    serializer = "{}SerializerVer$version".format(java_name)
+
+    return JType(java_type)\
+            .op(read="{}.readFrom(bb)".format(serializer),
+                write="{}.writeTo(bb, $name)".format(serializer),
+                default=default_value,
+                funnel="{}.putTo($name, sink)".format(serializer)
+               )
+
+def gen_list_jtype(java_base_name):
+    # read op assumes the class has a public final static field READER that implements
+    # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer
+    # write op assumes class implements Writeable
+    return JType("List<{}>".format(java_base_name)) \
+        .op(
+            read= 'ChannelUtils.readList(bb, $length, {}Ver$version.READER)'.format(java_base_name), \
+            write='ChannelUtils.writeList(bb, $name)',
+            default="ImmutableList.<{}>of()".format(java_base_name),
+            funnel='FunnelUtils.putList($name, sink)'
+            )
+
+def gen_fixed_length_string_jtype(length):
+    return JType('String').op(
+              read='ChannelUtils.readFixedLengthString(bb, {})'.format(length),
+              write='ChannelUtils.writeFixedLengthString(bb, $name, {})'.format(length),
+              default='""',
+              funnel='sink.putUnencodedChars($name)'
+            )
 
 ##### Predefined JType mappings
 # 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)')
+        .op(read='ChannelUtils.readList(bb, $length, U8.READER)',
+            write='ChannelUtils.writeList(bb, $name)',
+            default='ImmutableList.<U8>of()',
+            funnel='FunnelUtils.putList($name, sink)'
+           )
 u16 = JType('int', 'short') \
         .op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))', pub_type=True) \
         .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
@@ -240,7 +296,8 @@
         .op(
                 read='ChannelUtils.readList(bb, $length, U32.READER)',
                 write='ChannelUtils.writeList(bb, $name)',
-                default="ImmutableList.<U32>of()");
+                default="ImmutableList.<U32>of()",
+                funnel="FunnelUtils.putList($name, sink)")
 u8obj = JType('U8', 'U8') \
         .op(read='U8.of(bb.readByte())', write='bb.writeByte($name.getRaw())', default="U8.ZERO")
 u32obj = JType('U32', 'U32') \
@@ -250,36 +307,27 @@
 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")
-actions_list = JType('List<OFAction>') \
-        .op(read='ChannelUtils.readList(bb, $length, OFActionVer$version.READER)',
-            write='ChannelUtils.writeList(bb, $name);',
-            default='ImmutableList.<OFAction>of()')
-instructions_list = JType('List<OFInstruction>') \
-        .op(read='ChannelUtils.readList(bb, $length, OFInstructionVer$version.READER)', \
-            write='ChannelUtils.writeList(bb, $name)',
-            default='ImmutableList.<OFInstruction>of()')
-buckets_list = JType('List<OFBucket>') \
-        .op(read='ChannelUtils.readList(bb, $length, OFBucketVer$version.READER)',
-            write='ChannelUtils.writeList(bb, $name)',
-            default='ImmutableList.<OFBucket>of()')
-port_desc_list = JType('List<OFPortDesc>') \
-        .op(read='ChannelUtils.readList(bb, $length, OFPortDescVer$version.READER)',
-            write='ChannelUtils.writeList(bb, $name)',
-            default='ImmutableList.<OFPortDesc>of()')
+# 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 = gen_list_jtype("OFAction")
+instructions_list = gen_list_jtype("OFInstruction")
+buckets_list = gen_list_jtype("OFBucket")
+port_desc_list = gen_list_jtype("OFPortDesc")
+packet_queue_list = gen_list_jtype("OFPacketQueue")
 port_desc = JType('OFPortDesc') \
         .op(read='OFPortDescVer$version.READER.readFrom(bb)', \
             write='$name.writeTo(bb)')
-packet_queue_list = JType('List<OFPacketQueue>') \
-        .op(read='ChannelUtils.readList(bb, $length, OFPacketQueueVer$version.READER)',
-            write='ChannelUtils.writeList(bb, $name);',
-            default='ImmutableList.<OFPacketQueue>of()')
-octets = JType('byte[]') \
+octets = JType('byte[]')\
         .op(read='ChannelUtils.readBytes(bb, $length)', \
             write='bb.writeBytes($name)', \
-            default="new byte[0]");
+            default="new byte[0]",
+            funnel="sink.putBytes($name)"
+            );
 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)")
@@ -287,22 +335,11 @@
         .op(read="MacAddress.read6Bytes(bb)", \
             write="$name.write6Bytes(bb)",
             default="MacAddress.NONE")
-port_name = JType('String') \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 16)',
-            default='""')
-desc_str = JType('String') \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 256)',
-            default='""')
-serial_num = JType('String') \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)',
-            default='""')
-table_name = JType('String') \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)',
-            default='""')
+
+port_name = gen_fixed_length_string_jtype(16)
+desc_str = gen_fixed_length_string_jtype(256)
+serial_num = gen_fixed_length_string_jtype(32)
+table_name = gen_fixed_length_string_jtype(32)
 ipv4 = JType("IPv4Address") \
         .op(read="IPv4Address.read4Bytes(bb)", \
             write="$name.write4Bytes(bb)",
@@ -311,9 +348,7 @@
         .op(read="IPv6Address.read16Bytes(bb)", \
             write="$name.write16Bytes(bb)",
             default='IPv6Address.NONE')
-packetin_reason = JType("OFPacketInReason")\
-        .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)",
-            write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)")
+packetin_reason = gen_enum_jtype("OFPacketInReason")
 transport_port = JType("TransportPort")\
         .op(read="TransportPort.read2Bytes(bb)",
             write="$name.write2Bytes(bb)",
@@ -323,9 +358,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 +415,61 @@
 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')
+table_id_default_zero = JType("TableId") \
+        .op(read='TableId.readByte(bb)',
+            write='$name.writeByte(bb)',
+            default='TableId.ZERO')
+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")
+of_type = JType("OFType", 'byte') \
+            .op(read='bb.readByte()', write='bb.writeByte($name)')
+action_type= gen_enum_jtype("OFActionType")\
+               .set_priv_type("short")\
+               .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
+instruction_type = gen_enum_jtype("OFInstructionType")\
+               .set_priv_type('short') \
+               .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
+buffer_id = JType("OFBufferId") \
+            .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())", default="OFBufferId.NO_BUFFER")
+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')
+action_type_set = JType("Set<OFActionType>") \
+        .op(read='ChannelUtilsVer10.readSupportedActions(bb)',
+            write='ChannelUtilsVer10.writeSupportedActions(bb, $name)',
+            default='ImmutableSet.<OFActionType>of()',
+            funnel='ChannelUtilsVer10.putSupportedActionsTo($name, sink)')
+of_group = JType("OFGroup") \
+         .op(version=ANY, read="OFGroup.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFGroup.ALL")
+# the outgroup field of of_flow_stats_request has a special default value
+of_group_default_any = JType("OFGroup") \
+         .op(version=ANY, read="OFGroup.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFGroup.ANY")
+buffer_id = JType("OFBufferId") \
+         .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())", default="OFBufferId.NO_BUFFER")
+lag_id = JType("LagId") \
+         .op(version=ANY, read="LagId.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="LagId.NONE")
+vrf = JType("VRF") \
+         .op(version=ANY, read="VRF.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="VRF.ZERO")
+class_id = JType("ClassId") \
+         .op(version=ANY, read="ClassId.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="ClassId.NONE")
+boolean_value = JType('OFBooleanValue', 'OFBooleanValue') \
+        .op(read='OFBooleanValue.of(bb.readByte() != 0)', write='bb.writeByte($name.getInt())', default="OFBooleanValue.FALSE")
 
 generic_t = JType("T")
 
@@ -420,6 +502,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
@@ -474,11 +557,37 @@
         '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_oxm_bsn_lag_id' : { 'value' : lag_id },
+        'of_oxm_bsn_lag_id_masked' : { 'value' : lag_id, 'value_mask' : lag_id },
+
+        'of_oxm_bsn_vrf' : { 'value' : vrf },
+        'of_oxm_bsn_vrf_masked' : { 'value' : vrf, 'value_mask' : vrf },
+
+        'of_oxm_bsn_global_vrf_allowed' : { 'value' : boolean_value },
+        'of_oxm_bsn_global_vrf_allowed_masked' : { 'value' : boolean_value, 'value_mask' : boolean_value },
+
+        'of_oxm_bsn_l3_interface_class_id' : { 'value' : class_id },
+        'of_oxm_bsn_l3_interface_class_id_masked' : { 'value' : class_id, 'value_mask' : class_id },
+
+        'of_oxm_bsn_l3_src_class_id' : { 'value' : class_id },
+        'of_oxm_bsn_l3_src_class_id_masked' : { 'value' : class_id, 'value_mask' : class_id },
+
+        'of_oxm_bsn_l3_dst_class_id' : { 'value' : class_id },
+        'of_oxm_bsn_l3_dst_class_id_masked' : { 'value' : class_id, 'value_mask' : class_id },
+
         '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 },
+        'of_bsn_set_pktin_suppression_request': { 'enabled': boolean },
+        'of_flow_stats_request': { 'out_group': of_group_default_any },
 }
 
 
@@ -489,41 +598,20 @@
     for protocol in of_g.ir.values():
         for enum in protocol.enums:
             java_name = name_c_to_caps_camel(re.sub(r'_t$', "", enum.name))
-            if enum.is_bitmask:
-                java_type = "Set<{}>".format(java_name)
-                default_value = "ImmutableSet.<{}>of()".format(java_name)
-            else:
-                java_type = java_name
-                default_value = "null"
-            enum_types[enum.name] = \
-                    JType(java_type)\
-                      .op(read="{}SerializerVer$version.readFrom(bb)".format(java_name),
-                          write="{}SerializerVer$version.writeTo(bb, $name)".format(java_name),
-                          default=default_value)
+
+            enum_types[enum.name] = gen_enum_jtype(java_name, enum.is_bitmask)
     return enum_types
 
 def make_match_field_jtype(sub_type_name="?"):
     return JType("MatchField<{}>".format(sub_type_name))
 
 
-# Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}>
-def make_standard_list_jtype(c_type):
+def list_cname_to_java_name(c_type):
     m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
     if not m:
         raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
     base_name = m.group(1)
-    java_base_name = name_c_to_caps_camel(base_name)
-
-    # read op assumes the class has a public final static field READER that implements
-    # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer
-    # write op assumes class implements Writeable
-    return JType("List<OF{}>".format(java_base_name)) \
-        .op(
-            read= 'ChannelUtils.readList(bb, $length, OF{}Ver$version.READER)'.format(java_base_name), \
-            write='ChannelUtils.writeList(bb, $name)',
-            default="ImmutableList.<OF{}>of()".format(java_base_name)
-            )
-
+    return "OF" + name_c_to_caps_camel(base_name)
 
 
 #### main entry point for conversion of LOXI types (c_types) Java types.
@@ -535,24 +623,35 @@
     if obj_name in exceptions and field_name in exceptions[obj_name]:
         return exceptions[obj_name][field_name]
     elif ( obj_name == "of_header" or loxi_utils.class_is_message(obj_name)) and field_name == "type" and c_type == "uint8_t":
-        return JType("OFType", 'byte') \
-            .op(read='bb.readByte()', write='bb.writeByte($name)')
+        return of_type
     elif field_name == "type" and re.match(r'of_action.*', obj_name):
-        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)
+        return action_type
+    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 instruction_type
+    elif obj_name in ("of_flow_add", "of_flow_modify", "of_flow_modify_strict", "of_delete_strict") and  field_name == "table_id" and c_type == "uint8_t":
+        return table_id_default_zero
     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")
+        return buffer_id
+    elif field_name == "group_id" and c_type == "uint32_t":
+        return of_group
+    elif field_name == 'datapath_id':
+        return datapath_id
+    elif field_name == 'actions' and obj_name == 'of_features_reply':
+        return action_type_set
     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):
-        return make_standard_list_jtype(c_type)
+        return gen_list_jtype(list_cname_to_java_name(c_type))
     elif c_type in enum_java_types():
         return enum_java_types()[c_type]
     else:
diff --git a/java_gen/pre-written/pom.xml b/java_gen/pre-written/pom.xml
index ea9a43f..5715704 100644
--- a/java_gen/pre-written/pom.xml
+++ b/java_gen/pre-written/pom.xml
@@ -10,7 +10,7 @@
 
     <groupId>org.projectfloodlight</groupId>
     <artifactId>openflowj</artifactId>
-    <version>0.2.0-SNAPSHOT</version>
+    <version>0.3.0-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <name>OpenFlowJ-Loxi</name>
@@ -37,12 +37,12 @@
         <dependency>
             <groupId>com.google.code.findbugs</groupId>
             <artifactId>annotations</artifactId>
-            <version>2.0.1</version>
+            <version>2.0.2</version>
         </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
-            <version>4.8.2</version>
+            <version>4.11</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -53,7 +53,7 @@
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>14.0.1</version>
+            <version>15.0</version>
         </dependency>
     </dependencies>
     <build>
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java
index e17796a..68ca86d 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java
@@ -1,5 +1,13 @@
 package org.projectfloodlight.openflow.protocol;
 
-public class OFMatchBmap {
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+
+import com.google.common.hash.PrimitiveSink;
+
+public class OFMatchBmap implements PrimitiveSinkable{
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+    }
 
 }
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..5d37987 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
@@ -1,8 +1,11 @@
 package org.projectfloodlight.openflow.protocol;
 
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+
 
 /**
  * Base interface of all OpenFlow objects (e.g., messages, actions, stats, etc.)
  */
-public interface OFObject extends Writeable {
+public interface OFObject extends Writeable, PrimitiveSinkable {
+    OFVersion getVersion();
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
index ac48c8d..c6ba116 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
@@ -9,13 +9,15 @@
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 import org.projectfloodlight.openflow.protocol.match.MatchField;
 import org.projectfloodlight.openflow.protocol.match.MatchFields;
-import org.projectfloodlight.openflow.types.OFValueType;
-import org.projectfloodlight.openflow.util.ChannelUtils;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.types.OFValueType;
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+import org.projectfloodlight.openflow.util.ChannelUtils;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.hash.PrimitiveSink;
 
-public class OFOxmList implements Iterable<OFOxm<?>>, Writeable {
+public class OFOxmList implements Iterable<OFOxm<?>>, Writeable, PrimitiveSinkable {
     private final Map<MatchFields, OFOxm<?>> oxmMap;
 
     public final static OFOxmList EMPTY = new OFOxmList(ImmutableMap.<MatchFields, OFOxm<?>>of());
@@ -124,5 +126,12 @@
         return "OFOxmList" + oxmMap;
     }
 
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        for (OFOxm<?> o : this) {
+            o.putTo(sink);
+        }
+    }
+
 
 }
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..1831626 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
@@ -1,6 +1,7 @@
 package org.projectfloodlight.openflow.protocol.match;
 
 import org.projectfloodlight.openflow.types.ArpOpcode;
+import org.projectfloodlight.openflow.types.ClassId;
 import org.projectfloodlight.openflow.types.EthType;
 import org.projectfloodlight.openflow.types.ICMPv4Code;
 import org.projectfloodlight.openflow.types.ICMPv4Type;
@@ -10,7 +11,10 @@
 import org.projectfloodlight.openflow.types.IpDscp;
 import org.projectfloodlight.openflow.types.IpEcn;
 import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.LagId;
 import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFBitMask128;
+import org.projectfloodlight.openflow.types.OFBooleanValue;
 import org.projectfloodlight.openflow.types.OFMetadata;
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.OFValueType;
@@ -19,6 +23,7 @@
 import org.projectfloodlight.openflow.types.U8;
 import org.projectfloodlight.openflow.types.VlanPcp;
 import org.projectfloodlight.openflow.types.VlanVid;
+import org.projectfloodlight.openflow.types.VRF;
 
 @SuppressWarnings("unchecked")
 public class MatchField<F extends OFValueType<F>> {
@@ -80,35 +85,35 @@
 
     public final static MatchField<TransportPort> TCP_SRC = new MatchField<TransportPort>(
             "tcp_src", MatchFields.TCP_SRC,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.TCP));
 
     public final static MatchField<TransportPort> TCP_DST = new MatchField<TransportPort>(
             "tcp_dst", MatchFields.TCP_DST,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.TCP));
 
     public final static MatchField<TransportPort> UDP_SRC = new MatchField<TransportPort>(
             "udp_src", MatchFields.UDP_SRC,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_UDP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.UDP));
 
     public final static MatchField<TransportPort> UDP_DST = new MatchField<TransportPort>(
             "udp_dst", MatchFields.UDP_DST,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_UDP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.UDP));
 
     public final static MatchField<TransportPort> SCTP_SRC = new MatchField<TransportPort>(
             "sctp_src", MatchFields.SCTP_SRC,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_SCTP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.SCTP));
 
     public final static MatchField<TransportPort> SCTP_DST = new MatchField<TransportPort>(
             "sctp_dst", MatchFields.SCTP_DST,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_SCTP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.SCTP));
 
     public final static MatchField<ICMPv4Type> ICMPV4_TYPE = new MatchField<ICMPv4Type>(
             "icmpv4_src", MatchFields.ICMPV4_TYPE,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_ICMP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.ICMP));
 
     public final static MatchField<ICMPv4Code> ICMPV4_CODE = new MatchField<ICMPv4Code>(
             "icmpv4_dst", MatchFields.ICMPV4_CODE,
-            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_ICMP));
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.ICMP));
 
     public final static MatchField<ArpOpcode> ARP_OP = new MatchField<ArpOpcode>(
             "arp_op", MatchFields.ARP_OP,
@@ -144,11 +149,11 @@
 
     public final static MatchField<U8> ICMPV6_TYPE =
             new MatchField<U8>("icmpv6_type", MatchFields.ICMPV6_TYPE,
-                    new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_IPv6_ICMP));
+                    new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IPv6_ICMP));
 
     public final static MatchField<U8> ICMPV6_CODE =
             new MatchField<U8>("icmpv6_code", MatchFields.ICMPV6_CODE,
-                    new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_IPv6_ICMP));
+                    new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IPv6_ICMP));
 
     public final static MatchField<IPv6Address> IPV6_ND_TARGET =
             new MatchField<IPv6Address>("ipv6_nd_target", MatchFields.IPV6_ND_TARGET,
@@ -170,6 +175,27 @@
             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 final static MatchField<LagId> BSN_LAG_ID =
+            new MatchField<LagId>("bsn_lag_id", MatchFields.BSN_LAG_ID);
+
+    public final static MatchField<VRF> BSN_VRF =
+            new MatchField<VRF>("bsn_vrf", MatchFields.BSN_VRF);
+
+    public final static MatchField<OFBooleanValue> BSN_GLOBAL_VRF_ALLOWED =
+            new MatchField<OFBooleanValue>("bsn_global_vrf_allowed", MatchFields.BSN_GLOBAL_VRF_ALLOWED);
+
+    public final static MatchField<ClassId> BSN_L3_INTERFACE_CLASS_ID =
+            new MatchField<ClassId>("bsn_l3_interface_class_id", MatchFields.BSN_L3_INTERFACE_CLASS_ID);
+
+    public final static MatchField<ClassId> BSN_L3_SRC_CLASS_ID =
+            new MatchField<ClassId>("bsn_l3_src_class_id", MatchFields.BSN_L3_SRC_CLASS_ID);
+
+    public final static MatchField<ClassId> BSN_L3_DST_CLASS_ID =
+            new MatchField<ClassId>("bsn_l3_dst_class_id", MatchFields.BSN_L3_DST_CLASS_ID);
+
     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..6d9b20e 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,12 @@
     IPV6_ND_SLL,
     IPV6_ND_TLL,
     MPLS_LABEL,
-    MPLS_TC
+    MPLS_TC,
+    BSN_IN_PORTS_128,
+    BSN_LAG_ID,
+    BSN_VRF,
+    BSN_GLOBAL_VRF_ALLOWED,
+    BSN_L3_INTERFACE_CLASS_ID,
+    BSN_L3_SRC_CLASS_ID,
+    BSN_L3_DST_CLASS_ID,
 }
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..ed7c0c8 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,10 +1,15 @@
 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;
+import org.projectfloodlight.openflow.protocol.match.Match;
+
+import com.google.common.hash.PrimitiveSink;
 
 /**
  * Collection of helper functions for reading and writing into ChannelBuffers
@@ -28,4 +33,71 @@
 
     }
 
+    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 int supportedActionsToWire(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);
+        return supportedActionsVal;
+    }
+
+    public static void putSupportedActionsTo(Set<OFActionType> supportedActions, PrimitiveSink sink) {
+        sink.putInt(supportedActionsToWire(supportedActions));
+    }
+
+    public static void writeSupportedActions(ChannelBuffer bb, Set<OFActionType> supportedActions) {
+        bb.writeInt(supportedActionsToWire(supportedActions));
+    }
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java
index 2a33a0e..bfedaeb 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java
@@ -2,63 +2,64 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 public class ArpOpcode implements OFValueType<ArpOpcode> {
 
     final static int LENGTH = 2;
 
-    private static final int ARP_OPCODE_VAL_REQUEST   = 1;
-    private static final int ARP_OPCODE_VAL_REPLY = 2;
-    private static final int ARP_OPCODE_VAL_REQUEST_REVERSE   = 3;
-    private static final int ARP_OPCODE_VAL_REPLY_REVERSE = 4;
-    private static final int ARP_OPCODE_VAL_DRARP_REQUEST = 5;
-    private static final int ARP_OPCODE_VAL_DRARP_REPLY   = 6;
-    private static final int ARP_OPCODE_VAL_DRARP_ERROR   = 7;
-    private static final int ARP_OPCODE_VAL_INARP_REQUEST = 8;
-    private static final int ARP_OPCODE_VAL_INARP_REPLY   = 9;
-    private static final int ARP_OPCODE_VAL_ARP_NAK   = 10;
-    private static final int ARP_OPCODE_VAL_MARS_REQUEST  = 11;
-    private static final int ARP_OPCODE_VAL_MARS_MULTI    = 12;
-    private static final int ARP_OPCODE_VAL_MARS_MSERV    = 13;
-    private static final int ARP_OPCODE_VAL_MARS_JOIN = 14;
-    private static final int ARP_OPCODE_VAL_MARS_LEAVE    = 15;
-    private static final int ARP_OPCODE_VAL_MARS_NAK  = 16;
-    private static final int ARP_OPCODE_VAL_MARS_UNSERV   = 17;
-    private static final int ARP_OPCODE_VAL_MARS_SJOIN    = 18;
-    private static final int ARP_OPCODE_VAL_MARS_SLEAVE   = 19;
-    private static final int ARP_OPCODE_VAL_MARS_GROUPLIST_REQUEST    = 20;
-    private static final int ARP_OPCODE_VAL_MARS_GROUPLIST_REPLY  = 21;
-    private static final int ARP_OPCODE_VAL_MARS_REDIRECT_MAP = 22;
-    private static final int ARP_OPCODE_VAL_MAPOS_UNARP   = 23;
-    private static final int ARP_OPCODE_VAL_OP_EXP1   = 24;
-    private static final int ARP_OPCODE_VAL_OP_EXP2   = 25;
+    private static final int VAL_REQUEST   = 1;
+    private static final int VAL_REPLY = 2;
+    private static final int VAL_REQUEST_REVERSE   = 3;
+    private static final int VAL_REPLY_REVERSE = 4;
+    private static final int VAL_DRARP_REQUEST = 5;
+    private static final int VAL_DRARP_REPLY   = 6;
+    private static final int VAL_DRARP_ERROR   = 7;
+    private static final int VAL_INARP_REQUEST = 8;
+    private static final int VAL_INARP_REPLY   = 9;
+    private static final int VAL_ARP_NAK   = 10;
+    private static final int VAL_MARS_REQUEST  = 11;
+    private static final int VAL_MARS_MULTI    = 12;
+    private static final int VAL_MARS_MSERV    = 13;
+    private static final int VAL_MARS_JOIN = 14;
+    private static final int VAL_MARS_LEAVE    = 15;
+    private static final int VAL_MARS_NAK  = 16;
+    private static final int VAL_MARS_UNSERV   = 17;
+    private static final int VAL_MARS_SJOIN    = 18;
+    private static final int VAL_MARS_SLEAVE   = 19;
+    private static final int VAL_MARS_GROUPLIST_REQUEST    = 20;
+    private static final int VAL_MARS_GROUPLIST_REPLY  = 21;
+    private static final int VAL_MARS_REDIRECT_MAP = 22;
+    private static final int VAL_MAPOS_UNARP   = 23;
+    private static final int VAL_OP_EXP1   = 24;
+    private static final int VAL_OP_EXP2   = 25;
 
-    public static final ArpOpcode ARP_OPCODE_REQUEST  = new ArpOpcode(ARP_OPCODE_VAL_REQUEST);
-    public static final ArpOpcode ARP_OPCODE_REPLY    = new ArpOpcode(ARP_OPCODE_VAL_REPLY);
-    public static final ArpOpcode ARP_OPCODE_REQUEST_REVERSE  = new ArpOpcode(ARP_OPCODE_VAL_REQUEST_REVERSE);
-    public static final ArpOpcode ARP_OPCODE_REPLY_REVERSE    = new ArpOpcode(ARP_OPCODE_VAL_REPLY_REVERSE);
-    public static final ArpOpcode ARP_OPCODE_DRARP_REQUEST    = new ArpOpcode(ARP_OPCODE_VAL_DRARP_REQUEST);
-    public static final ArpOpcode ARP_OPCODE_DRARP_REPLY  = new ArpOpcode(ARP_OPCODE_VAL_DRARP_REPLY);
-    public static final ArpOpcode ARP_OPCODE_DRARP_ERROR  = new ArpOpcode(ARP_OPCODE_VAL_DRARP_ERROR);
-    public static final ArpOpcode ARP_OPCODE_INARP_REQUEST    = new ArpOpcode(ARP_OPCODE_VAL_INARP_REQUEST);
-    public static final ArpOpcode ARP_OPCODE_INARP_REPLY  = new ArpOpcode(ARP_OPCODE_VAL_INARP_REPLY);
-    public static final ArpOpcode ARP_OPCODE_ARP_NAK  = new ArpOpcode(ARP_OPCODE_VAL_ARP_NAK);
-    public static final ArpOpcode ARP_OPCODE_MARS_REQUEST = new ArpOpcode(ARP_OPCODE_VAL_MARS_REQUEST);
-    public static final ArpOpcode ARP_OPCODE_MARS_MULTI   = new ArpOpcode(ARP_OPCODE_VAL_MARS_MULTI);
-    public static final ArpOpcode ARP_OPCODE_MARS_MSERV   = new ArpOpcode(ARP_OPCODE_VAL_MARS_MSERV);
-    public static final ArpOpcode ARP_OPCODE_MARS_JOIN    = new ArpOpcode(ARP_OPCODE_VAL_MARS_JOIN);
-    public static final ArpOpcode ARP_OPCODE_MARS_LEAVE   = new ArpOpcode(ARP_OPCODE_VAL_MARS_LEAVE);
-    public static final ArpOpcode ARP_OPCODE_MARS_NAK = new ArpOpcode(ARP_OPCODE_VAL_MARS_NAK);
-    public static final ArpOpcode ARP_OPCODE_MARS_UNSERV  = new ArpOpcode(ARP_OPCODE_VAL_MARS_UNSERV);
-    public static final ArpOpcode ARP_OPCODE_MARS_SJOIN   = new ArpOpcode(ARP_OPCODE_VAL_MARS_SJOIN);
-    public static final ArpOpcode ARP_OPCODE_MARS_SLEAVE  = new ArpOpcode(ARP_OPCODE_VAL_MARS_SLEAVE);
-    public static final ArpOpcode ARP_OPCODE_MARS_GROUPLIST_REQUEST   = new ArpOpcode(ARP_OPCODE_VAL_MARS_GROUPLIST_REQUEST);
-    public static final ArpOpcode ARP_OPCODE_MARS_GROUPLIST_REPLY = new ArpOpcode(ARP_OPCODE_VAL_MARS_GROUPLIST_REPLY);
-    public static final ArpOpcode ARP_OPCODE_MARS_REDIRECT_MAP    = new ArpOpcode(ARP_OPCODE_VAL_MARS_REDIRECT_MAP);
-    public static final ArpOpcode ARP_OPCODE_MAPOS_UNARP  = new ArpOpcode(ARP_OPCODE_VAL_MAPOS_UNARP);
-    public static final ArpOpcode ARP_OPCODE_OP_EXP1  = new ArpOpcode(ARP_OPCODE_VAL_OP_EXP1);
-    public static final ArpOpcode ARP_OPCODE_OP_EXP2  = new ArpOpcode(ARP_OPCODE_VAL_OP_EXP2);
+    public static final ArpOpcode REQUEST  = new ArpOpcode(VAL_REQUEST);
+    public static final ArpOpcode REPLY    = new ArpOpcode(VAL_REPLY);
+    public static final ArpOpcode REQUEST_REVERSE  = new ArpOpcode(VAL_REQUEST_REVERSE);
+    public static final ArpOpcode REPLY_REVERSE    = new ArpOpcode(VAL_REPLY_REVERSE);
+    public static final ArpOpcode DRARP_REQUEST    = new ArpOpcode(VAL_DRARP_REQUEST);
+    public static final ArpOpcode DRARP_REPLY  = new ArpOpcode(VAL_DRARP_REPLY);
+    public static final ArpOpcode DRARP_ERROR  = new ArpOpcode(VAL_DRARP_ERROR);
+    public static final ArpOpcode INARP_REQUEST    = new ArpOpcode(VAL_INARP_REQUEST);
+    public static final ArpOpcode INARP_REPLY  = new ArpOpcode(VAL_INARP_REPLY);
+    public static final ArpOpcode ARP_NAK  = new ArpOpcode(VAL_ARP_NAK);
+    public static final ArpOpcode MARS_REQUEST = new ArpOpcode(VAL_MARS_REQUEST);
+    public static final ArpOpcode MARS_MULTI   = new ArpOpcode(VAL_MARS_MULTI);
+    public static final ArpOpcode MARS_MSERV   = new ArpOpcode(VAL_MARS_MSERV);
+    public static final ArpOpcode MARS_JOIN    = new ArpOpcode(VAL_MARS_JOIN);
+    public static final ArpOpcode MARS_LEAVE   = new ArpOpcode(VAL_MARS_LEAVE);
+    public static final ArpOpcode MARS_NAK = new ArpOpcode(VAL_MARS_NAK);
+    public static final ArpOpcode MARS_UNSERV  = new ArpOpcode(VAL_MARS_UNSERV);
+    public static final ArpOpcode MARS_SJOIN   = new ArpOpcode(VAL_MARS_SJOIN);
+    public static final ArpOpcode MARS_SLEAVE  = new ArpOpcode(VAL_MARS_SLEAVE);
+    public static final ArpOpcode MARS_GROUPLIST_REQUEST   = new ArpOpcode(VAL_MARS_GROUPLIST_REQUEST);
+    public static final ArpOpcode MARS_GROUPLIST_REPLY = new ArpOpcode(VAL_MARS_GROUPLIST_REPLY);
+    public static final ArpOpcode MARS_REDIRECT_MAP    = new ArpOpcode(VAL_MARS_REDIRECT_MAP);
+    public static final ArpOpcode MAPOS_UNARP  = new ArpOpcode(VAL_MAPOS_UNARP);
+    public static final ArpOpcode OP_EXP1  = new ArpOpcode(VAL_OP_EXP1);
+    public static final ArpOpcode OP_EXP2  = new ArpOpcode(VAL_OP_EXP2);
 
     private static final int MIN_OPCODE = 0;
     private static final int MAX_OPCODE = 0xFFFF;
@@ -90,56 +91,56 @@
         switch (opcode) {
             case NONE_VAL:
                 return NONE;
-            case ARP_OPCODE_VAL_REQUEST:
-                return ARP_OPCODE_REQUEST;
-            case ARP_OPCODE_VAL_REPLY:
-                return ARP_OPCODE_REPLY;
-            case ARP_OPCODE_VAL_REQUEST_REVERSE:
-                return ARP_OPCODE_REQUEST_REVERSE;
-            case ARP_OPCODE_VAL_REPLY_REVERSE:
-                return ARP_OPCODE_REPLY_REVERSE;
-            case ARP_OPCODE_VAL_DRARP_REQUEST:
-                return ARP_OPCODE_DRARP_REQUEST;
-            case ARP_OPCODE_VAL_DRARP_REPLY:
-                return ARP_OPCODE_DRARP_REPLY;
-            case ARP_OPCODE_VAL_DRARP_ERROR:
-                return ARP_OPCODE_DRARP_ERROR;
-            case ARP_OPCODE_VAL_INARP_REQUEST:
-                return ARP_OPCODE_INARP_REQUEST;
-            case ARP_OPCODE_VAL_INARP_REPLY:
-                return ARP_OPCODE_INARP_REPLY;
-            case ARP_OPCODE_VAL_ARP_NAK:
-                return ARP_OPCODE_ARP_NAK;
-            case ARP_OPCODE_VAL_MARS_REQUEST:
-                return ARP_OPCODE_MARS_REQUEST;
-            case ARP_OPCODE_VAL_MARS_MULTI:
-                return ARP_OPCODE_MARS_MULTI;
-            case ARP_OPCODE_VAL_MARS_MSERV:
-                return ARP_OPCODE_MARS_MSERV;
-            case ARP_OPCODE_VAL_MARS_JOIN:
-                return ARP_OPCODE_MARS_JOIN;
-            case ARP_OPCODE_VAL_MARS_LEAVE:
-                return ARP_OPCODE_MARS_LEAVE;
-            case ARP_OPCODE_VAL_MARS_NAK:
-                return ARP_OPCODE_MARS_NAK;
-            case ARP_OPCODE_VAL_MARS_UNSERV:
-                return ARP_OPCODE_MARS_UNSERV;
-            case ARP_OPCODE_VAL_MARS_SJOIN:
-                return ARP_OPCODE_MARS_SJOIN;
-            case ARP_OPCODE_VAL_MARS_SLEAVE:
-                return ARP_OPCODE_MARS_SLEAVE;
-            case ARP_OPCODE_VAL_MARS_GROUPLIST_REQUEST:
-                return ARP_OPCODE_MARS_GROUPLIST_REQUEST;
-            case ARP_OPCODE_VAL_MARS_GROUPLIST_REPLY:
-                return ARP_OPCODE_MARS_GROUPLIST_REPLY;
-            case ARP_OPCODE_VAL_MARS_REDIRECT_MAP:
-                return ARP_OPCODE_MARS_REDIRECT_MAP;
-            case ARP_OPCODE_VAL_MAPOS_UNARP:
-                return ARP_OPCODE_MAPOS_UNARP;
-            case ARP_OPCODE_VAL_OP_EXP1:
-                return ARP_OPCODE_OP_EXP1;
-            case ARP_OPCODE_VAL_OP_EXP2:
-                return ARP_OPCODE_OP_EXP2;
+            case VAL_REQUEST:
+                return REQUEST;
+            case VAL_REPLY:
+                return REPLY;
+            case VAL_REQUEST_REVERSE:
+                return REQUEST_REVERSE;
+            case VAL_REPLY_REVERSE:
+                return REPLY_REVERSE;
+            case VAL_DRARP_REQUEST:
+                return DRARP_REQUEST;
+            case VAL_DRARP_REPLY:
+                return DRARP_REPLY;
+            case VAL_DRARP_ERROR:
+                return DRARP_ERROR;
+            case VAL_INARP_REQUEST:
+                return INARP_REQUEST;
+            case VAL_INARP_REPLY:
+                return INARP_REPLY;
+            case VAL_ARP_NAK:
+                return ARP_NAK;
+            case VAL_MARS_REQUEST:
+                return MARS_REQUEST;
+            case VAL_MARS_MULTI:
+                return MARS_MULTI;
+            case VAL_MARS_MSERV:
+                return MARS_MSERV;
+            case VAL_MARS_JOIN:
+                return MARS_JOIN;
+            case VAL_MARS_LEAVE:
+                return MARS_LEAVE;
+            case VAL_MARS_NAK:
+                return MARS_NAK;
+            case VAL_MARS_UNSERV:
+                return MARS_UNSERV;
+            case VAL_MARS_SJOIN:
+                return MARS_SJOIN;
+            case VAL_MARS_SLEAVE:
+                return MARS_SLEAVE;
+            case VAL_MARS_GROUPLIST_REQUEST:
+                return MARS_GROUPLIST_REQUEST;
+            case VAL_MARS_GROUPLIST_REPLY:
+                return MARS_GROUPLIST_REPLY;
+            case VAL_MARS_REDIRECT_MAP:
+                return MARS_REDIRECT_MAP;
+            case VAL_MAPOS_UNARP:
+                return MAPOS_UNARP;
+            case VAL_OP_EXP1:
+                return OP_EXP1;
+            case VAL_OP_EXP2:
+                return OP_EXP2;
             default:
                 return new ArpOpcode(opcode);
         }
@@ -189,4 +190,9 @@
         return UnsignedInts.compare(opcode, o.opcode);
     }
 
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putShort((short) this.opcode);
+    }
+
 }
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
new file mode 100644
index 0000000..b082f8b
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
@@ -0,0 +1,87 @@
+package org.projectfloodlight.openflow.types;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.UnsignedInts;
+
+@Immutable
+public class ClassId implements OFValueType<ClassId> {
+    static final int LENGTH = 4;
+
+    private final static int NONE_VAL = 0;
+    public final static ClassId NONE = new ClassId(NONE_VAL);
+
+    private final int rawValue;
+
+    private ClassId(final int rawValue) {
+        this.rawValue = rawValue;
+    }
+
+    public static ClassId of(final int raw) {
+        if(raw == NONE_VAL)
+            return NONE;
+
+        return new ClassId(raw);
+    }
+
+    public int getInt() {
+        return rawValue;
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public String toString() {
+        return Integer.toString(rawValue);
+    }
+
+    @Override
+    public ClassId applyMask(ClassId mask) {
+        return ClassId.of(rawValue & mask.rawValue);    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + rawValue;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ClassId other = (ClassId) obj;
+        if (rawValue != other.rawValue)
+            return false;
+        return true;
+    }
+
+    public void write4Bytes(ChannelBuffer c) {
+        c.writeInt(rawValue);
+    }
+
+    public static ClassId read4Bytes(ChannelBuffer c) {
+        return ClassId.of(c.readInt());
+    }
+
+    @Override
+    public int compareTo(ClassId o) {
+        return UnsignedInts.compare(rawValue, rawValue);
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(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..79fa14f
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java
@@ -0,0 +1,87 @@
+package org.projectfloodlight.openflow.types;
+
+import org.projectfloodlight.openflow.annotations.Immutable;
+import org.projectfloodlight.openflow.util.HexString;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.Longs;
+import com.google.common.primitives.UnsignedLongs;
+
+/**
+ * Abstraction of a datapath ID that can be set and/or accessed as either a
+ * long value or a colon-separated string. Immutable
+ *
+ * @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
+ */
+@Immutable
+public class DatapathId implements PrimitiveSinkable, Comparable<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 static DatapathId of(byte[] bytes) {
+        return new DatapathId(Longs.fromByteArray(bytes));
+    }
+
+    public long getLong() {
+        return rawValue;
+    }
+
+    public U64 getUnsignedLong() {
+        return U64.of(rawValue);
+    }
+
+    public byte[] getBytes() {
+        return Longs.toByteArray(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;
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putLong(rawValue);
+    }
+
+    @Override
+    public int compareTo(DatapathId o) {
+        return UnsignedLongs.compare(rawValue, o.rawValue);
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java
index 7031a0d..c5f4f86 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java
@@ -2,6 +2,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 
@@ -260,5 +261,10 @@
         return UnsignedInts.compare(rawValue, o.rawValue);
     }
 
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(rawValue);
+    }
+
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java
index c66486f..6466eee 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java
@@ -2,6 +2,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Shorts;
 
 /**
@@ -84,4 +85,9 @@
     public int compareTo(ICMPv4Code o) {
         return Shorts.compare(code, o.code);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putShort(code);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java
index 594aaec..a0aa152 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java
@@ -2,71 +2,72 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Shorts;
 
 public class ICMPv4Type implements OFValueType<ICMPv4Type> {
     final static int LENGTH = 1;
 
-    private static final short ICMPV4_TYPE_VAL_ECHO_REPLY    = 0;
-    private static final short ICMPV4_TYPE_VAL_DESTINATION_UNREACHABLE   = 3;
-    private static final short ICMPV4_TYPE_VAL_SOURCE_QUENCH = 4;
-    private static final short ICMPV4_TYPE_VAL_REDIRECT  = 5;
-    private static final short ICMPV4_TYPE_VAL_ALTERNATE_HOST_ADDRESS    = 6;
-    private static final short ICMPV4_TYPE_VAL_ECHO  = 8;
-    private static final short ICMPV4_TYPE_VAL_ROUTER_ADVERTISEMENT  = 9;
-    private static final short ICMPV4_TYPE_VAL_ROUTER_SOLICITATION   = 10;
-    private static final short ICMPV4_TYPE_VAL_TIME_EXCEEDED = 11;
-    private static final short ICMPV4_TYPE_VAL_PARAMETER_PROBLEM = 12;
-    private static final short ICMPV4_TYPE_VAL_TIMESTAMP = 13;
-    private static final short ICMPV4_TYPE_VAL_TIMESTAMP_REPLY   = 14;
-    private static final short ICMPV4_TYPE_VAL_INFORMATION_REQUEST   = 15;
-    private static final short ICMPV4_TYPE_VAL_INFORMATION_REPLY = 16;
-    private static final short ICMPV4_TYPE_VAL_ADDRESS_MASK_REQUEST  = 17;
-    private static final short ICMPV4_TYPE_VAL_ADDRESS_MASK_REPLY    = 18;
-    private static final short ICMPV4_TYPE_VAL_TRACEROUTE    = 30;
-    private static final short ICMPV4_TYPE_VAL_DATAGRAM_CONVERSION_ERROR = 31;
-    private static final short ICMPV4_TYPE_VAL_MOBILE_HOST_REDIRECT  = 32;
-    private static final short ICMPV4_TYPE_VAL_IPV6_WHERE_ARE_YOU    = 33;
-    private static final short ICMPV4_TYPE_VAL_IPV6_I_AM_HERE    = 34;
-    private static final short ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REQUEST   = 35;
-    private static final short ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REPLY = 36;
-    private static final short ICMPV4_TYPE_VAL_DOMAIN_NAME_REQUEST   = 37;
-    private static final short ICMPV4_TYPE_VAL_DOMAIN_NAME_REPLY = 38;
-    private static final short ICMPV4_TYPE_VAL_SKIP  = 39;
-    private static final short ICMPV4_TYPE_VAL_PHOTURIS  = 40;
-    private static final short ICMPV4_TYPE_VAL_EXPERIMENTAL_MOBILITY = 41;
+    private static final short VAL_ECHO_REPLY    = 0;
+    private static final short VAL_DESTINATION_UNREACHABLE   = 3;
+    private static final short VAL_SOURCE_QUENCH = 4;
+    private static final short VAL_REDIRECT  = 5;
+    private static final short VAL_ALTERNATE_HOST_ADDRESS    = 6;
+    private static final short VAL_ECHO  = 8;
+    private static final short VAL_ROUTER_ADVERTISEMENT  = 9;
+    private static final short VAL_ROUTER_SOLICITATION   = 10;
+    private static final short VAL_TIME_EXCEEDED = 11;
+    private static final short VAL_PARAMETER_PROBLEM = 12;
+    private static final short VAL_TIMESTAMP = 13;
+    private static final short VAL_TIMESTAMP_REPLY   = 14;
+    private static final short VAL_INFORMATION_REQUEST   = 15;
+    private static final short VAL_INFORMATION_REPLY = 16;
+    private static final short VAL_ADDRESS_MASK_REQUEST  = 17;
+    private static final short VAL_ADDRESS_MASK_REPLY    = 18;
+    private static final short VAL_TRACEROUTE    = 30;
+    private static final short VAL_DATAGRAM_CONVERSION_ERROR = 31;
+    private static final short VAL_MOBILE_HOST_REDIRECT  = 32;
+    private static final short VAL_IPV6_WHERE_ARE_YOU    = 33;
+    private static final short VAL_IPV6_I_AM_HERE    = 34;
+    private static final short VAL_MOBILE_REGISTRATION_REQUEST   = 35;
+    private static final short VAL_MOBILE_REGISTRATION_REPLY = 36;
+    private static final short VAL_DOMAIN_NAME_REQUEST   = 37;
+    private static final short VAL_DOMAIN_NAME_REPLY = 38;
+    private static final short VAL_SKIP  = 39;
+    private static final short VAL_PHOTURIS  = 40;
+    private static final short VAL_EXPERIMENTAL_MOBILITY = 41;
 
-    public static final ICMPv4Type ICMPV4_TYPE_ECHO_REPLY   = new ICMPv4Type(ICMPV4_TYPE_VAL_ECHO_REPLY);
-    public static final ICMPv4Type ICMPV4_TYPE_DESTINATION_UNREACHABLE  = new ICMPv4Type(ICMPV4_TYPE_VAL_DESTINATION_UNREACHABLE);
-    public static final ICMPv4Type ICMPV4_TYPE_SOURCE_QUENCH    = new ICMPv4Type(ICMPV4_TYPE_VAL_SOURCE_QUENCH);
-    public static final ICMPv4Type ICMPV4_TYPE_REDIRECT = new ICMPv4Type(ICMPV4_TYPE_VAL_REDIRECT);
-    public static final ICMPv4Type ICMPV4_TYPE_ALTERNATE_HOST_ADDRESS   = new ICMPv4Type(ICMPV4_TYPE_VAL_ALTERNATE_HOST_ADDRESS);
-    public static final ICMPv4Type ICMPV4_TYPE_ECHO = new ICMPv4Type(ICMPV4_TYPE_VAL_ECHO);
-    public static final ICMPv4Type ICMPV4_TYPE_ROUTER_ADVERTISEMENT = new ICMPv4Type(ICMPV4_TYPE_VAL_ROUTER_ADVERTISEMENT);
-    public static final ICMPv4Type ICMPV4_TYPE_ROUTER_SOLICITATION  = new ICMPv4Type(ICMPV4_TYPE_VAL_ROUTER_SOLICITATION);
-    public static final ICMPv4Type ICMPV4_TYPE_TIME_EXCEEDED    = new ICMPv4Type(ICMPV4_TYPE_VAL_TIME_EXCEEDED);
-    public static final ICMPv4Type ICMPV4_TYPE_PARAMETER_PROBLEM    = new ICMPv4Type(ICMPV4_TYPE_VAL_PARAMETER_PROBLEM);
-    public static final ICMPv4Type ICMPV4_TYPE_TIMESTAMP    = new ICMPv4Type(ICMPV4_TYPE_VAL_TIMESTAMP);
-    public static final ICMPv4Type ICMPV4_TYPE_TIMESTAMP_REPLY  = new ICMPv4Type(ICMPV4_TYPE_VAL_TIMESTAMP_REPLY);
-    public static final ICMPv4Type ICMPV4_TYPE_INFORMATION_REQUEST  = new ICMPv4Type(ICMPV4_TYPE_VAL_INFORMATION_REQUEST);
-    public static final ICMPv4Type ICMPV4_TYPE_INFORMATION_REPLY    = new ICMPv4Type(ICMPV4_TYPE_VAL_INFORMATION_REPLY);
-    public static final ICMPv4Type ICMPV4_TYPE_ADDRESS_MASK_REQUEST = new ICMPv4Type(ICMPV4_TYPE_VAL_ADDRESS_MASK_REQUEST);
-    public static final ICMPv4Type ICMPV4_TYPE_ADDRESS_MASK_REPLY   = new ICMPv4Type(ICMPV4_TYPE_VAL_ADDRESS_MASK_REPLY);
-    public static final ICMPv4Type ICMPV4_TYPE_TRACEROUTE   = new ICMPv4Type(ICMPV4_TYPE_VAL_TRACEROUTE);
-    public static final ICMPv4Type ICMPV4_TYPE_DATAGRAM_CONVERSION_ERROR    = new ICMPv4Type(ICMPV4_TYPE_VAL_DATAGRAM_CONVERSION_ERROR);
-    public static final ICMPv4Type ICMPV4_TYPE_MOBILE_HOST_REDIRECT = new ICMPv4Type(ICMPV4_TYPE_VAL_MOBILE_HOST_REDIRECT);
-    public static final ICMPv4Type ICMPV4_TYPE_IPV6_WHERE_ARE_YOU  = new ICMPv4Type(ICMPV4_TYPE_VAL_IPV6_WHERE_ARE_YOU);
-    public static final ICMPv4Type ICMPV4_TYPE_IPV6_I_AM_HERE = new ICMPv4Type(ICMPV4_TYPE_VAL_IPV6_I_AM_HERE);
-    public static final ICMPv4Type ICMPV4_TYPE_MOBILE_REGISTRATION_REQUEST  = new ICMPv4Type(ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REQUEST);
-    public static final ICMPv4Type ICMPV4_TYPE_MOBILE_REGISTRATION_REPLY    = new ICMPv4Type(ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REPLY);
-    public static final ICMPv4Type ICMPV4_TYPE_DOMAIN_NAME_REQUEST  = new ICMPv4Type(ICMPV4_TYPE_VAL_DOMAIN_NAME_REQUEST);
-    public static final ICMPv4Type ICMPV4_TYPE_DOMAIN_NAME_REPLY    = new ICMPv4Type(ICMPV4_TYPE_VAL_DOMAIN_NAME_REPLY);
-    public static final ICMPv4Type ICMPV4_TYPE_SKIP = new ICMPv4Type(ICMPV4_TYPE_VAL_SKIP);
-    public static final ICMPv4Type ICMPV4_TYPE_PHOTURIS = new ICMPv4Type(ICMPV4_TYPE_VAL_PHOTURIS);
-    public static final ICMPv4Type ICMPV4_TYPE_EXPERIMENTAL_MOBILITY    = new ICMPv4Type(ICMPV4_TYPE_VAL_EXPERIMENTAL_MOBILITY);
+    public static final ICMPv4Type ECHO_REPLY   = new ICMPv4Type(VAL_ECHO_REPLY);
+    public static final ICMPv4Type DESTINATION_UNREACHABLE  = new ICMPv4Type(VAL_DESTINATION_UNREACHABLE);
+    public static final ICMPv4Type SOURCE_QUENCH    = new ICMPv4Type(VAL_SOURCE_QUENCH);
+    public static final ICMPv4Type REDIRECT = new ICMPv4Type(VAL_REDIRECT);
+    public static final ICMPv4Type ALTERNATE_HOST_ADDRESS   = new ICMPv4Type(VAL_ALTERNATE_HOST_ADDRESS);
+    public static final ICMPv4Type ECHO = new ICMPv4Type(VAL_ECHO);
+    public static final ICMPv4Type ROUTER_ADVERTISEMENT = new ICMPv4Type(VAL_ROUTER_ADVERTISEMENT);
+    public static final ICMPv4Type ROUTER_SOLICITATION  = new ICMPv4Type(VAL_ROUTER_SOLICITATION);
+    public static final ICMPv4Type TIME_EXCEEDED    = new ICMPv4Type(VAL_TIME_EXCEEDED);
+    public static final ICMPv4Type PARAMETER_PROBLEM    = new ICMPv4Type(VAL_PARAMETER_PROBLEM);
+    public static final ICMPv4Type TIMESTAMP    = new ICMPv4Type(VAL_TIMESTAMP);
+    public static final ICMPv4Type TIMESTAMP_REPLY  = new ICMPv4Type(VAL_TIMESTAMP_REPLY);
+    public static final ICMPv4Type INFORMATION_REQUEST  = new ICMPv4Type(VAL_INFORMATION_REQUEST);
+    public static final ICMPv4Type INFORMATION_REPLY    = new ICMPv4Type(VAL_INFORMATION_REPLY);
+    public static final ICMPv4Type ADDRESS_MASK_REQUEST = new ICMPv4Type(VAL_ADDRESS_MASK_REQUEST);
+    public static final ICMPv4Type ADDRESS_MASK_REPLY   = new ICMPv4Type(VAL_ADDRESS_MASK_REPLY);
+    public static final ICMPv4Type TRACEROUTE   = new ICMPv4Type(VAL_TRACEROUTE);
+    public static final ICMPv4Type DATAGRAM_CONVERSION_ERROR    = new ICMPv4Type(VAL_DATAGRAM_CONVERSION_ERROR);
+    public static final ICMPv4Type MOBILE_HOST_REDIRECT = new ICMPv4Type(VAL_MOBILE_HOST_REDIRECT);
+    public static final ICMPv4Type IPV6_WHERE_ARE_YOU  = new ICMPv4Type(VAL_IPV6_WHERE_ARE_YOU);
+    public static final ICMPv4Type IPV6_I_AM_HERE = new ICMPv4Type(VAL_IPV6_I_AM_HERE);
+    public static final ICMPv4Type MOBILE_REGISTRATION_REQUEST  = new ICMPv4Type(VAL_MOBILE_REGISTRATION_REQUEST);
+    public static final ICMPv4Type MOBILE_REGISTRATION_REPLY    = new ICMPv4Type(VAL_MOBILE_REGISTRATION_REPLY);
+    public static final ICMPv4Type DOMAIN_NAME_REQUEST  = new ICMPv4Type(VAL_DOMAIN_NAME_REQUEST);
+    public static final ICMPv4Type DOMAIN_NAME_REPLY    = new ICMPv4Type(VAL_DOMAIN_NAME_REPLY);
+    public static final ICMPv4Type SKIP = new ICMPv4Type(VAL_SKIP);
+    public static final ICMPv4Type PHOTURIS = new ICMPv4Type(VAL_PHOTURIS);
+    public static final ICMPv4Type EXPERIMENTAL_MOBILITY    = new ICMPv4Type(VAL_EXPERIMENTAL_MOBILITY);
 
-    // HACK alert - we're disapproriating ICMPV4_TYPE_ECHO_REPLY (value 0) as 'none' as well
-    public static final ICMPv4Type NONE   = ICMPV4_TYPE_ECHO_REPLY;
+    // HACK alert - we're disapproriating ECHO_REPLY (value 0) as 'none' as well
+    public static final ICMPv4Type NONE   = ECHO_REPLY;
 
     public static final ICMPv4Type NO_MASK = new ICMPv4Type((short)0xFFFF);
     public static final ICMPv4Type FULL_MASK = new ICMPv4Type((short)0x0000);
@@ -84,62 +85,62 @@
         if (type < MIN_TYPE || type > MAX_TYPE)
             throw new IllegalArgumentException("Invalid ICMPv4 type: " + type);
         switch (type) {
-            case ICMPV4_TYPE_VAL_ECHO_REPLY:
-                return ICMPV4_TYPE_ECHO_REPLY;
-            case ICMPV4_TYPE_VAL_DESTINATION_UNREACHABLE:
-                return ICMPV4_TYPE_DESTINATION_UNREACHABLE;
-            case ICMPV4_TYPE_VAL_SOURCE_QUENCH:
-                return ICMPV4_TYPE_SOURCE_QUENCH;
-            case ICMPV4_TYPE_VAL_REDIRECT:
-                return ICMPV4_TYPE_REDIRECT;
-            case ICMPV4_TYPE_VAL_ALTERNATE_HOST_ADDRESS:
-                return ICMPV4_TYPE_ALTERNATE_HOST_ADDRESS;
-            case ICMPV4_TYPE_VAL_ECHO:
-                return ICMPV4_TYPE_ECHO;
-            case ICMPV4_TYPE_VAL_ROUTER_ADVERTISEMENT:
-                return ICMPV4_TYPE_ROUTER_ADVERTISEMENT;
-            case ICMPV4_TYPE_VAL_ROUTER_SOLICITATION:
-                return ICMPV4_TYPE_ROUTER_SOLICITATION;
-            case ICMPV4_TYPE_VAL_TIME_EXCEEDED:
-                return ICMPV4_TYPE_TIME_EXCEEDED;
-            case ICMPV4_TYPE_VAL_PARAMETER_PROBLEM:
-                return ICMPV4_TYPE_PARAMETER_PROBLEM;
-            case ICMPV4_TYPE_VAL_TIMESTAMP:
-                return ICMPV4_TYPE_TIMESTAMP;
-            case ICMPV4_TYPE_VAL_TIMESTAMP_REPLY:
-                return ICMPV4_TYPE_TIMESTAMP_REPLY;
-            case ICMPV4_TYPE_VAL_INFORMATION_REQUEST:
-                return ICMPV4_TYPE_INFORMATION_REQUEST;
-            case ICMPV4_TYPE_VAL_INFORMATION_REPLY:
-                return ICMPV4_TYPE_INFORMATION_REPLY;
-            case ICMPV4_TYPE_VAL_ADDRESS_MASK_REQUEST:
-                return ICMPV4_TYPE_ADDRESS_MASK_REQUEST;
-            case ICMPV4_TYPE_VAL_ADDRESS_MASK_REPLY:
-                return ICMPV4_TYPE_ADDRESS_MASK_REPLY;
-            case ICMPV4_TYPE_VAL_TRACEROUTE:
-                return ICMPV4_TYPE_TRACEROUTE;
-            case ICMPV4_TYPE_VAL_DATAGRAM_CONVERSION_ERROR:
-                return ICMPV4_TYPE_DATAGRAM_CONVERSION_ERROR;
-            case ICMPV4_TYPE_VAL_MOBILE_HOST_REDIRECT:
-                return ICMPV4_TYPE_MOBILE_HOST_REDIRECT;
-            case ICMPV4_TYPE_VAL_IPV6_WHERE_ARE_YOU:
-                return ICMPV4_TYPE_IPV6_WHERE_ARE_YOU;
-            case ICMPV4_TYPE_VAL_IPV6_I_AM_HERE:
-                return ICMPV4_TYPE_IPV6_I_AM_HERE;
-            case ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REQUEST:
-                return ICMPV4_TYPE_MOBILE_REGISTRATION_REQUEST;
-            case ICMPV4_TYPE_VAL_MOBILE_REGISTRATION_REPLY:
-                return ICMPV4_TYPE_MOBILE_REGISTRATION_REPLY;
-            case ICMPV4_TYPE_VAL_DOMAIN_NAME_REQUEST:
-                return ICMPV4_TYPE_DOMAIN_NAME_REQUEST;
-            case ICMPV4_TYPE_VAL_DOMAIN_NAME_REPLY:
-                return ICMPV4_TYPE_DOMAIN_NAME_REPLY;
-            case ICMPV4_TYPE_VAL_SKIP:
-                return ICMPV4_TYPE_SKIP;
-            case ICMPV4_TYPE_VAL_PHOTURIS:
-                return ICMPV4_TYPE_PHOTURIS;
-            case ICMPV4_TYPE_VAL_EXPERIMENTAL_MOBILITY:
-                return ICMPV4_TYPE_EXPERIMENTAL_MOBILITY;
+            case VAL_ECHO_REPLY:
+                return ECHO_REPLY;
+            case VAL_DESTINATION_UNREACHABLE:
+                return DESTINATION_UNREACHABLE;
+            case VAL_SOURCE_QUENCH:
+                return SOURCE_QUENCH;
+            case VAL_REDIRECT:
+                return REDIRECT;
+            case VAL_ALTERNATE_HOST_ADDRESS:
+                return ALTERNATE_HOST_ADDRESS;
+            case VAL_ECHO:
+                return ECHO;
+            case VAL_ROUTER_ADVERTISEMENT:
+                return ROUTER_ADVERTISEMENT;
+            case VAL_ROUTER_SOLICITATION:
+                return ROUTER_SOLICITATION;
+            case VAL_TIME_EXCEEDED:
+                return TIME_EXCEEDED;
+            case VAL_PARAMETER_PROBLEM:
+                return PARAMETER_PROBLEM;
+            case VAL_TIMESTAMP:
+                return TIMESTAMP;
+            case VAL_TIMESTAMP_REPLY:
+                return TIMESTAMP_REPLY;
+            case VAL_INFORMATION_REQUEST:
+                return INFORMATION_REQUEST;
+            case VAL_INFORMATION_REPLY:
+                return INFORMATION_REPLY;
+            case VAL_ADDRESS_MASK_REQUEST:
+                return ADDRESS_MASK_REQUEST;
+            case VAL_ADDRESS_MASK_REPLY:
+                return ADDRESS_MASK_REPLY;
+            case VAL_TRACEROUTE:
+                return TRACEROUTE;
+            case VAL_DATAGRAM_CONVERSION_ERROR:
+                return DATAGRAM_CONVERSION_ERROR;
+            case VAL_MOBILE_HOST_REDIRECT:
+                return MOBILE_HOST_REDIRECT;
+            case VAL_IPV6_WHERE_ARE_YOU:
+                return IPV6_WHERE_ARE_YOU;
+            case VAL_IPV6_I_AM_HERE:
+                return IPV6_I_AM_HERE;
+            case VAL_MOBILE_REGISTRATION_REQUEST:
+                return MOBILE_REGISTRATION_REQUEST;
+            case VAL_MOBILE_REGISTRATION_REPLY:
+                return MOBILE_REGISTRATION_REPLY;
+            case VAL_DOMAIN_NAME_REQUEST:
+                return DOMAIN_NAME_REQUEST;
+            case VAL_DOMAIN_NAME_REPLY:
+                return DOMAIN_NAME_REPLY;
+            case VAL_SKIP:
+                return SKIP;
+            case VAL_PHOTURIS:
+                return PHOTURIS;
+            case VAL_EXPERIMENTAL_MOBILITY:
+                return EXPERIMENTAL_MOBILITY;
             default:
                 return new ICMPv4Type(type);
         }
@@ -193,4 +194,10 @@
     public int compareTo(ICMPv4Type o) {
         return Shorts.compare(type, o.type);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putShort(type);
+    }
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
index 77b792f..51d10f3 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
@@ -4,6 +4,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 
@@ -152,4 +153,10 @@
     public int compareTo(IPv4Address o) {
         return UnsignedInts.compare(rawValue, o.rawValue);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(rawValue);
+    }
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
index b58de1a..1aad85b 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
@@ -5,6 +5,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Longs;
 
 /**
@@ -308,4 +309,10 @@
         else
             return Longs.compare(raw2, o.raw2);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putLong(raw1);
+        sink.putLong(raw2);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java
index 45bbf4b..de49b51 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java
@@ -3,6 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 public class IPv6FlowLabel implements OFValueType<IPv6FlowLabel> {
@@ -76,4 +77,9 @@
     public int compareTo(IPv6FlowLabel o) {
         return UnsignedInts.compare(label, o.label);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(this.label);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java
index ec78315..27596b7 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java
@@ -3,6 +3,8 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
+
 public enum IpDscp implements OFValueType<IpDscp> {
     DSCP_0((byte)0),
     DSCP_1((byte)1),
@@ -244,4 +246,9 @@
     public byte getDscpValue() {
         return dscp;
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putByte(dscp);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java
index 7e1cdf0..654df01 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java
@@ -3,6 +3,8 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
+
 public enum IpEcn implements OFValueType<IpEcn> {
     ECN_00((byte)0),
     ECN_01((byte)1),
@@ -63,4 +65,9 @@
     public byte getEcnValue() {
         return ecn;
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putByte(ecn);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java
index f0f79ec..69f497e 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java
@@ -2,6 +2,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Shorts;
 
 /**
@@ -16,293 +17,293 @@
 
     private final short proto;
 
-    static final short IP_PROTO_NUM_HOPOPT  = 0x00;
-    static final short IP_PROTO_NUM_ICMP    = 0x01;
-    static final short IP_PROTO_NUM_IGMP    = 0x02;
-    static final short IP_PROTO_NUM_GGP = 0x03;
-    static final short IP_PROTO_NUM_IPv4    = 0x04;
-    static final short IP_PROTO_NUM_ST  = 0x05;
-    static final short IP_PROTO_NUM_TCP = 0x06;
-    static final short IP_PROTO_NUM_CBT = 0x07;
-    static final short IP_PROTO_NUM_EGP = 0x08;
-    static final short IP_PROTO_NUM_IGP = 0x09;
-    static final short IP_PROTO_NUM_BBN_RCC_MON = 0x0A;
-    static final short IP_PROTO_NUM_NVP_II  = 0x0B;
-    static final short IP_PROTO_NUM_PUP = 0x0C;
-    static final short IP_PROTO_NUM_ARGUS   = 0x0D;
-    static final short IP_PROTO_NUM_EMCON   = 0x0E;
-    static final short IP_PROTO_NUM_XNET    = 0x0F;
-    static final short IP_PROTO_NUM_CHAOS   = 0x10;
-    static final short IP_PROTO_NUM_UDP = 0x11;
-    static final short IP_PROTO_NUM_MUX = 0x12;
-    static final short IP_PROTO_NUM_DCN_MEAS    = 0x13;
-    static final short IP_PROTO_NUM_HMP = 0x14;
-    static final short IP_PROTO_NUM_PRM = 0x15;
-    static final short IP_PROTO_NUM_XNS_IDP = 0x16;
-    static final short IP_PROTO_NUM_TRUNK_1 = 0x17;
-    static final short IP_PROTO_NUM_TRUNK_2 = 0x18;
-    static final short IP_PROTO_NUM_LEAF_1  = 0x19;
-    static final short IP_PROTO_NUM_LEAF_2  = 0x1A;
-    static final short IP_PROTO_NUM_RDP = 0x1B;
-    static final short IP_PROTO_NUM_IRTP    = 0x1C;
-    static final short IP_PROTO_NUM_ISO_TP4 = 0x1D;
-    static final short IP_PROTO_NUM_NETBLT  = 0x1E;
-    static final short IP_PROTO_NUM_MFE_NSP = 0x1F;
-    static final short IP_PROTO_NUM_MERIT_INP   = 0x20;
-    static final short IP_PROTO_NUM_DCCP    = 0x21;
-    static final short IP_PROTO_NUM_3PC = 0x22;
-    static final short IP_PROTO_NUM_IDPR    = 0x23;
-    static final short IP_PROTO_NUM_XTP = 0x24;
-    static final short IP_PROTO_NUM_DDP = 0x25;
-    static final short IP_PROTO_NUM_IDPR_CMTP   = 0x26;
-    static final short IP_PROTO_NUM_TP_PP   = 0x27;
-    static final short IP_PROTO_NUM_IL  = 0x28;
-    static final short IP_PROTO_NUM_IPv6    = 0x29;
-    static final short IP_PROTO_NUM_SDRP    = 0x2A;
-    static final short IP_PROTO_NUM_IPv6_ROUTE  = 0x2B;
-    static final short IP_PROTO_NUM_IPv6_FRAG   = 0x2C;
-    static final short IP_PROTO_NUM_IDRP    = 0x2D;
-    static final short IP_PROTO_NUM_RSVP    = 0x2E;
-    static final short IP_PROTO_NUM_GRE = 0x2F;
-    static final short IP_PROTO_NUM_MHRP    = 0x30;
-    static final short IP_PROTO_NUM_BNA = 0x31;
-    static final short IP_PROTO_NUM_ESP = 0x32;
-    static final short IP_PROTO_NUM_AH  = 0x33;
-    static final short IP_PROTO_NUM_I_NLSP  = 0x34;
-    static final short IP_PROTO_NUM_SWIPE   = 0x35;
-    static final short IP_PROTO_NUM_NARP    = 0x36;
-    static final short IP_PROTO_NUM_MOBILE  = 0x37;
-    static final short IP_PROTO_NUM_TLSP    = 0x38;
-    static final short IP_PROTO_NUM_SKIP    = 0x39;
-    static final short IP_PROTO_NUM_IPv6_ICMP   = 0x3A;
-    static final short IP_PROTO_NUM_IPv6_NO_NXT = 0x3B;
-    static final short IP_PROTO_NUM_IPv6_OPTS   = 0x3C;
-    static final short IP_PROTO_NUM_HOST_INTERNAL   = 0x3D;
-    static final short IP_PROTO_NUM_CFTP    = 0x3E;
-    static final short IP_PROTO_NUM_LOCAL_NET   = 0x3F;
-    static final short IP_PROTO_NUM_SAT_EXPAK   = 0x40;
-    static final short IP_PROTO_NUM_KRYPTOLAN   = 0x41;
-    static final short IP_PROTO_NUM_RVD = 0x42;
-    static final short IP_PROTO_NUM_IPPC    = 0x43;
-    static final short IP_PROTO_NUM_DIST_FS = 0x44;
-    static final short IP_PROTO_NUM_SAT_MON = 0x45;
-    static final short IP_PROTO_NUM_VISA    = 0x46;
-    static final short IP_PROTO_NUM_IPCV    = 0x47;
-    static final short IP_PROTO_NUM_CPNX    = 0x48;
-    static final short IP_PROTO_NUM_CPHB    = 0x49;
-    static final short IP_PROTO_NUM_WSN = 0x4A;
-    static final short IP_PROTO_NUM_PVP = 0x4B;
-    static final short IP_PROTO_NUM_BR_SAT_MON  = 0x4C;
-    static final short IP_PROTO_NUM_SUN_ND  = 0x4D;
-    static final short IP_PROTO_NUM_WB_MON  = 0x4E;
-    static final short IP_PROTO_NUM_WB_EXPAK    = 0x4F;
-    static final short IP_PROTO_NUM_ISO_IP  = 0x50;
-    static final short IP_PROTO_NUM_VMTP    = 0x51;
-    static final short IP_PROTO_NUM_SECURE_VMTP = 0x52;
-    static final short IP_PROTO_NUM_VINES   = 0x53;
-    static final short IP_PROTO_NUM_TTP_IPTM = 0x54;
-    static final short IP_PROTO_NUM_NSFNET_IGP  = 0x55;
-    static final short IP_PROTO_NUM_DGP = 0x56;
-    static final short IP_PROTO_NUM_TCF = 0x57;
-    static final short IP_PROTO_NUM_EIGRP   = 0x58;
-    static final short IP_PROTO_NUM_OSPF    = 0x59;
-    static final short IP_PROTO_NUM_Sprite_RPC  = 0x5A;
-    static final short IP_PROTO_NUM_LARP    = 0x5B;
-    static final short IP_PROTO_NUM_MTP = 0x5C;
-    static final short IP_PROTO_NUM_AX_25   = 0x5D;
-    static final short IP_PROTO_NUM_IPIP    = 0x5E;
-    static final short IP_PROTO_NUM_MICP    = 0x5F;
-    static final short IP_PROTO_NUM_SCC_SP  = 0x60;
-    static final short IP_PROTO_NUM_ETHERIP = 0x61;
-    static final short IP_PROTO_NUM_ENCAP   = 0x62;
-    static final short IP_PROTO_NUM_PRIVATE_ENCRYPT = 0x63;
-    static final short IP_PROTO_NUM_GMTP    = 0x64;
-    static final short IP_PROTO_NUM_IFMP    = 0x65;
-    static final short IP_PROTO_NUM_PNNI    = 0x66;
-    static final short IP_PROTO_NUM_PIM = 0x67;
-    static final short IP_PROTO_NUM_ARIS    = 0x68;
-    static final short IP_PROTO_NUM_SCPS    = 0x69;
-    static final short IP_PROTO_NUM_QNX = 0x6A;
-    static final short IP_PROTO_NUM_A_N = 0x6B;
-    static final short IP_PROTO_NUM_IP_COMP = 0x6C;
-    static final short IP_PROTO_NUM_SNP = 0x6D;
-    static final short IP_PROTO_NUM_COMPAQ_PEER = 0x6E;
-    static final short IP_PROTO_NUM_IPX_IN_IP   = 0x6F;
-    static final short IP_PROTO_NUM_VRRP    = 0x70;
-    static final short IP_PROTO_NUM_PGM = 0x71;
-    static final short IP_PROTO_NUM_ZERO_HOP    = 0x72;
-    static final short IP_PROTO_NUM_L2TP    = 0x73;
-    static final short IP_PROTO_NUM_DDX = 0x74;
-    static final short IP_PROTO_NUM_IATP    = 0x75;
-    static final short IP_PROTO_NUM_STP = 0x76;
-    static final short IP_PROTO_NUM_SRP = 0x77;
-    static final short IP_PROTO_NUM_UTI = 0x78;
-    static final short IP_PROTO_NUM_SMP = 0x79;
-    static final short IP_PROTO_NUM_SM  = 0x7A;
-    static final short IP_PROTO_NUM_PTP = 0x7B;
-    static final short IP_PROTO_NUM_IS_IS_OVER_IPv4 = 0x7C;
-    static final short IP_PROTO_NUM_FIRE    = 0x7D;
-    static final short IP_PROTO_NUM_CRTP    = 0x7E;
-    static final short IP_PROTO_NUM_CRUDP   = 0x7F;
-    static final short IP_PROTO_NUM_SSCOPMCE    = 0x80;
-    static final short IP_PROTO_NUM_IPLT    = 0x81;
-    static final short IP_PROTO_NUM_SPS = 0x82;
-    static final short IP_PROTO_NUM_PIPE    = 0x83;
-    static final short IP_PROTO_NUM_SCTP    = 0x84;
-    static final short IP_PROTO_NUM_FC  = 0x85;
-    static final short IP_PROTO_NUM_RSVP_E2E_IGNORE = 0x86;
-    static final short IP_PROTO_NUM_MOBILITY_HEADER = 0x87;
-    static final short IP_PROTO_NUM_UDP_LITE    = 0x88;
-    static final short IP_PROTO_NUM_MPLS_IN_IP  = 0x89;
-    static final short IP_PROTO_NUM_MANET   = 0x8A;
-    static final short IP_PROTO_NUM_HIP = 0x8B;
-    static final short IP_PROTO_NUM_SHIM6   = 0x8C;
+    static final short NUM_HOPOPT  = 0x00;
+    static final short NUM_ICMP    = 0x01;
+    static final short NUM_IGMP    = 0x02;
+    static final short NUM_GGP = 0x03;
+    static final short NUM_IPv4    = 0x04;
+    static final short NUM_ST  = 0x05;
+    static final short NUM_TCP = 0x06;
+    static final short NUM_CBT = 0x07;
+    static final short NUM_EGP = 0x08;
+    static final short NUM_IGP = 0x09;
+    static final short NUM_BBN_RCC_MON = 0x0A;
+    static final short NUM_NVP_II  = 0x0B;
+    static final short NUM_PUP = 0x0C;
+    static final short NUM_ARGUS   = 0x0D;
+    static final short NUM_EMCON   = 0x0E;
+    static final short NUM_XNET    = 0x0F;
+    static final short NUM_CHAOS   = 0x10;
+    static final short NUM_UDP = 0x11;
+    static final short NUM_MUX = 0x12;
+    static final short NUM_DCN_MEAS    = 0x13;
+    static final short NUM_HMP = 0x14;
+    static final short NUM_PRM = 0x15;
+    static final short NUM_XNS_IDP = 0x16;
+    static final short NUM_TRUNK_1 = 0x17;
+    static final short NUM_TRUNK_2 = 0x18;
+    static final short NUM_LEAF_1  = 0x19;
+    static final short NUM_LEAF_2  = 0x1A;
+    static final short NUM_RDP = 0x1B;
+    static final short NUM_IRTP    = 0x1C;
+    static final short NUM_ISO_TP4 = 0x1D;
+    static final short NUM_NETBLT  = 0x1E;
+    static final short NUM_MFE_NSP = 0x1F;
+    static final short NUM_MERIT_INP   = 0x20;
+    static final short NUM_DCCP    = 0x21;
+    static final short NUM_3PC = 0x22;
+    static final short NUM_IDPR    = 0x23;
+    static final short NUM_XTP = 0x24;
+    static final short NUM_DDP = 0x25;
+    static final short NUM_IDPR_CMTP   = 0x26;
+    static final short NUM_TP_PP   = 0x27;
+    static final short NUM_IL  = 0x28;
+    static final short NUM_IPv6    = 0x29;
+    static final short NUM_SDRP    = 0x2A;
+    static final short NUM_IPv6_ROUTE  = 0x2B;
+    static final short NUM_IPv6_FRAG   = 0x2C;
+    static final short NUM_IDRP    = 0x2D;
+    static final short NUM_RSVP    = 0x2E;
+    static final short NUM_GRE = 0x2F;
+    static final short NUM_MHRP    = 0x30;
+    static final short NUM_BNA = 0x31;
+    static final short NUM_ESP = 0x32;
+    static final short NUM_AH  = 0x33;
+    static final short NUM_I_NLSP  = 0x34;
+    static final short NUM_SWIPE   = 0x35;
+    static final short NUM_NARP    = 0x36;
+    static final short NUM_MOBILE  = 0x37;
+    static final short NUM_TLSP    = 0x38;
+    static final short NUM_SKIP    = 0x39;
+    static final short NUM_IPv6_ICMP   = 0x3A;
+    static final short NUM_IPv6_NO_NXT = 0x3B;
+    static final short NUM_IPv6_OPTS   = 0x3C;
+    static final short NUM_HOST_INTERNAL   = 0x3D;
+    static final short NUM_CFTP    = 0x3E;
+    static final short NUM_LOCAL_NET   = 0x3F;
+    static final short NUM_SAT_EXPAK   = 0x40;
+    static final short NUM_KRYPTOLAN   = 0x41;
+    static final short NUM_RVD = 0x42;
+    static final short NUM_IPPC    = 0x43;
+    static final short NUM_DIST_FS = 0x44;
+    static final short NUM_SAT_MON = 0x45;
+    static final short NUM_VISA    = 0x46;
+    static final short NUM_IPCV    = 0x47;
+    static final short NUM_CPNX    = 0x48;
+    static final short NUM_CPHB    = 0x49;
+    static final short NUM_WSN = 0x4A;
+    static final short NUM_PVP = 0x4B;
+    static final short NUM_BR_SAT_MON  = 0x4C;
+    static final short NUM_SUN_ND  = 0x4D;
+    static final short NUM_WB_MON  = 0x4E;
+    static final short NUM_WB_EXPAK    = 0x4F;
+    static final short NUM_ISO_IP  = 0x50;
+    static final short NUM_VMTP    = 0x51;
+    static final short NUM_SECURE_VMTP = 0x52;
+    static final short NUM_VINES   = 0x53;
+    static final short NUM_TTP_IPTM = 0x54;
+    static final short NUM_NSFNET_IGP  = 0x55;
+    static final short NUM_DGP = 0x56;
+    static final short NUM_TCF = 0x57;
+    static final short NUM_EIGRP   = 0x58;
+    static final short NUM_OSPF    = 0x59;
+    static final short NUM_Sprite_RPC  = 0x5A;
+    static final short NUM_LARP    = 0x5B;
+    static final short NUM_MTP = 0x5C;
+    static final short NUM_AX_25   = 0x5D;
+    static final short NUM_IPIP    = 0x5E;
+    static final short NUM_MICP    = 0x5F;
+    static final short NUM_SCC_SP  = 0x60;
+    static final short NUM_ETHERIP = 0x61;
+    static final short NUM_ENCAP   = 0x62;
+    static final short NUM_PRIVATE_ENCRYPT = 0x63;
+    static final short NUM_GMTP    = 0x64;
+    static final short NUM_IFMP    = 0x65;
+    static final short NUM_PNNI    = 0x66;
+    static final short NUM_PIM = 0x67;
+    static final short NUM_ARIS    = 0x68;
+    static final short NUM_SCPS    = 0x69;
+    static final short NUM_QNX = 0x6A;
+    static final short NUM_A_N = 0x6B;
+    static final short NUM_IP_COMP = 0x6C;
+    static final short NUM_SNP = 0x6D;
+    static final short NUM_COMPAQ_PEER = 0x6E;
+    static final short NUM_IPX_IN_IP   = 0x6F;
+    static final short NUM_VRRP    = 0x70;
+    static final short NUM_PGM = 0x71;
+    static final short NUM_ZERO_HOP    = 0x72;
+    static final short NUM_L2TP    = 0x73;
+    static final short NUM_DDX = 0x74;
+    static final short NUM_IATP    = 0x75;
+    static final short NUM_STP = 0x76;
+    static final short NUM_SRP = 0x77;
+    static final short NUM_UTI = 0x78;
+    static final short NUM_SMP = 0x79;
+    static final short NUM_SM  = 0x7A;
+    static final short NUM_PTP = 0x7B;
+    static final short NUM_IS_IS_OVER_IPv4 = 0x7C;
+    static final short NUM_FIRE    = 0x7D;
+    static final short NUM_CRTP    = 0x7E;
+    static final short NUM_CRUDP   = 0x7F;
+    static final short NUM_SSCOPMCE    = 0x80;
+    static final short NUM_IPLT    = 0x81;
+    static final short NUM_SPS = 0x82;
+    static final short NUM_PIPE    = 0x83;
+    static final short NUM_SCTP    = 0x84;
+    static final short NUM_FC  = 0x85;
+    static final short NUM_RSVP_E2E_IGNORE = 0x86;
+    static final short NUM_MOBILITY_HEADER = 0x87;
+    static final short NUM_UDP_LITE    = 0x88;
+    static final short NUM_MPLS_IN_IP  = 0x89;
+    static final short NUM_MANET   = 0x8A;
+    static final short NUM_HIP = 0x8B;
+    static final short NUM_SHIM6   = 0x8C;
 
-    public static final IpProtocol IP_PROTO_HOPOPT = new IpProtocol(IP_PROTO_NUM_HOPOPT);
-    public static final IpProtocol IP_PROTO_ICMP = new IpProtocol(IP_PROTO_NUM_ICMP);
-    public static final IpProtocol IP_PROTO_IGMP = new IpProtocol(IP_PROTO_NUM_IGMP);
-    public static final IpProtocol IP_PROTO_GGP = new IpProtocol(IP_PROTO_NUM_GGP);
-    public static final IpProtocol IP_PROTO_IPv4 = new IpProtocol(IP_PROTO_NUM_IPv4);
-    public static final IpProtocol IP_PROTO_ST = new IpProtocol(IP_PROTO_NUM_ST);
-    public static final IpProtocol IP_PROTO_TCP = new IpProtocol(IP_PROTO_NUM_TCP);
-    public static final IpProtocol IP_PROTO_CBT = new IpProtocol(IP_PROTO_NUM_CBT);
-    public static final IpProtocol IP_PROTO_EGP = new IpProtocol(IP_PROTO_NUM_EGP);
-    public static final IpProtocol IP_PROTO_IGP = new IpProtocol(IP_PROTO_NUM_IGP);
-    public static final IpProtocol IP_PROTO_BBN_RCC_MON = new IpProtocol(IP_PROTO_NUM_BBN_RCC_MON);
-    public static final IpProtocol IP_PROTO_NVP_II = new IpProtocol(IP_PROTO_NUM_NVP_II);
-    public static final IpProtocol IP_PROTO_PUP = new IpProtocol(IP_PROTO_NUM_PUP);
-    public static final IpProtocol IP_PROTO_ARGUS = new IpProtocol(IP_PROTO_NUM_ARGUS);
-    public static final IpProtocol IP_PROTO_EMCON = new IpProtocol(IP_PROTO_NUM_EMCON);
-    public static final IpProtocol IP_PROTO_XNET = new IpProtocol(IP_PROTO_NUM_XNET);
-    public static final IpProtocol IP_PROTO_CHAOS = new IpProtocol(IP_PROTO_NUM_CHAOS);
-    public static final IpProtocol IP_PROTO_UDP = new IpProtocol(IP_PROTO_NUM_UDP);
-    public static final IpProtocol IP_PROTO_MUX = new IpProtocol(IP_PROTO_NUM_MUX);
-    public static final IpProtocol IP_PROTO_DCN_MEAS = new IpProtocol(IP_PROTO_NUM_DCN_MEAS);
-    public static final IpProtocol IP_PROTO_HMP = new IpProtocol(IP_PROTO_NUM_HMP);
-    public static final IpProtocol IP_PROTO_PRM = new IpProtocol(IP_PROTO_NUM_PRM);
-    public static final IpProtocol IP_PROTO_XNS_IDP = new IpProtocol(IP_PROTO_NUM_XNS_IDP);
-    public static final IpProtocol IP_PROTO_TRUNK_1 = new IpProtocol(IP_PROTO_NUM_TRUNK_1);
-    public static final IpProtocol IP_PROTO_TRUNK_2 = new IpProtocol(IP_PROTO_NUM_TRUNK_2);
-    public static final IpProtocol IP_PROTO_LEAF_1 = new IpProtocol(IP_PROTO_NUM_LEAF_1);
-    public static final IpProtocol IP_PROTO_LEAF_2 = new IpProtocol(IP_PROTO_NUM_LEAF_2);
-    public static final IpProtocol IP_PROTO_RDP = new IpProtocol(IP_PROTO_NUM_RDP);
-    public static final IpProtocol IP_PROTO_IRTP = new IpProtocol(IP_PROTO_NUM_IRTP);
-    public static final IpProtocol IP_PROTO_ISO_TP4 = new IpProtocol(IP_PROTO_NUM_ISO_TP4);
-    public static final IpProtocol IP_PROTO_NETBLT = new IpProtocol(IP_PROTO_NUM_NETBLT);
-    public static final IpProtocol IP_PROTO_MFE_NSP = new IpProtocol(IP_PROTO_NUM_MFE_NSP);
-    public static final IpProtocol IP_PROTO_MERIT_INP = new IpProtocol(IP_PROTO_NUM_MERIT_INP);
-    public static final IpProtocol IP_PROTO_DCCP = new IpProtocol(IP_PROTO_NUM_DCCP);
-    public static final IpProtocol IP_PROTO_3PC = new IpProtocol(IP_PROTO_NUM_3PC);
-    public static final IpProtocol IP_PROTO_IDPR = new IpProtocol(IP_PROTO_NUM_IDPR);
-    public static final IpProtocol IP_PROTO_XTP = new IpProtocol(IP_PROTO_NUM_XTP);
-    public static final IpProtocol IP_PROTO_DDP = new IpProtocol(IP_PROTO_NUM_DDP);
-    public static final IpProtocol IP_PROTO_IDPR_CMTP = new IpProtocol(IP_PROTO_NUM_IDPR_CMTP);
-    public static final IpProtocol IP_PROTO_TP_PP = new IpProtocol(IP_PROTO_NUM_TP_PP);
-    public static final IpProtocol IP_PROTO_IL = new IpProtocol(IP_PROTO_NUM_IL);
-    public static final IpProtocol IP_PROTO_IPv6 = new IpProtocol(IP_PROTO_NUM_IPv6);
-    public static final IpProtocol IP_PROTO_SDRP = new IpProtocol(IP_PROTO_NUM_SDRP);
-    public static final IpProtocol IP_PROTO_IPv6_ROUTE = new IpProtocol(IP_PROTO_NUM_IPv6_ROUTE);
-    public static final IpProtocol IP_PROTO_IPv6_FRAG = new IpProtocol(IP_PROTO_NUM_IPv6_FRAG);
-    public static final IpProtocol IP_PROTO_IDRP = new IpProtocol(IP_PROTO_NUM_IDRP);
-    public static final IpProtocol IP_PROTO_RSVP = new IpProtocol(IP_PROTO_NUM_RSVP);
-    public static final IpProtocol IP_PROTO_GRE = new IpProtocol(IP_PROTO_NUM_GRE);
-    public static final IpProtocol IP_PROTO_MHRP = new IpProtocol(IP_PROTO_NUM_MHRP);
-    public static final IpProtocol IP_PROTO_BNA = new IpProtocol(IP_PROTO_NUM_BNA);
-    public static final IpProtocol IP_PROTO_ESP = new IpProtocol(IP_PROTO_NUM_ESP);
-    public static final IpProtocol IP_PROTO_AH = new IpProtocol(IP_PROTO_NUM_AH);
-    public static final IpProtocol IP_PROTO_I_NLSP = new IpProtocol(IP_PROTO_NUM_I_NLSP);
-    public static final IpProtocol IP_PROTO_SWIPE = new IpProtocol(IP_PROTO_NUM_SWIPE);
-    public static final IpProtocol IP_PROTO_NARP = new IpProtocol(IP_PROTO_NUM_NARP);
-    public static final IpProtocol IP_PROTO_MOBILE = new IpProtocol(IP_PROTO_NUM_MOBILE);
-    public static final IpProtocol IP_PROTO_TLSP = new IpProtocol(IP_PROTO_NUM_TLSP);
-    public static final IpProtocol IP_PROTO_SKIP = new IpProtocol(IP_PROTO_NUM_SKIP);
-    public static final IpProtocol IP_PROTO_IPv6_ICMP = new IpProtocol(IP_PROTO_NUM_IPv6_ICMP);
-    public static final IpProtocol IP_PROTO_IPv6_NO_NXT = new IpProtocol(IP_PROTO_NUM_IPv6_NO_NXT);
-    public static final IpProtocol IP_PROTO_IPv6_OPTS = new IpProtocol(IP_PROTO_NUM_IPv6_OPTS);
-    public static final IpProtocol IP_PROTO_HOST_INTERNAL = new IpProtocol(IP_PROTO_NUM_HOST_INTERNAL);
-    public static final IpProtocol IP_PROTO_CFTP = new IpProtocol(IP_PROTO_NUM_CFTP);
-    public static final IpProtocol IP_PROTO_LOCAL_NET = new IpProtocol(IP_PROTO_NUM_LOCAL_NET);
-    public static final IpProtocol IP_PROTO_SAT_EXPAK = new IpProtocol(IP_PROTO_NUM_SAT_EXPAK);
-    public static final IpProtocol IP_PROTO_KRYPTOLAN = new IpProtocol(IP_PROTO_NUM_KRYPTOLAN);
-    public static final IpProtocol IP_PROTO_RVD = new IpProtocol(IP_PROTO_NUM_RVD);
-    public static final IpProtocol IP_PROTO_IPPC = new IpProtocol(IP_PROTO_NUM_IPPC);
-    public static final IpProtocol IP_PROTO_DIST_FS = new IpProtocol(IP_PROTO_NUM_DIST_FS);
-    public static final IpProtocol IP_PROTO_SAT_MON = new IpProtocol(IP_PROTO_NUM_SAT_MON);
-    public static final IpProtocol IP_PROTO_VISA = new IpProtocol(IP_PROTO_NUM_VISA);
-    public static final IpProtocol IP_PROTO_IPCV = new IpProtocol(IP_PROTO_NUM_IPCV);
-    public static final IpProtocol IP_PROTO_CPNX = new IpProtocol(IP_PROTO_NUM_CPNX);
-    public static final IpProtocol IP_PROTO_CPHB = new IpProtocol(IP_PROTO_NUM_CPHB);
-    public static final IpProtocol IP_PROTO_WSN = new IpProtocol(IP_PROTO_NUM_WSN);
-    public static final IpProtocol IP_PROTO_PVP = new IpProtocol(IP_PROTO_NUM_PVP);
-    public static final IpProtocol IP_PROTO_BR_SAT_MON = new IpProtocol(IP_PROTO_NUM_BR_SAT_MON);
-    public static final IpProtocol IP_PROTO_SUN_ND = new IpProtocol(IP_PROTO_NUM_SUN_ND);
-    public static final IpProtocol IP_PROTO_WB_MON = new IpProtocol(IP_PROTO_NUM_WB_MON);
-    public static final IpProtocol IP_PROTO_WB_EXPAK = new IpProtocol(IP_PROTO_NUM_WB_EXPAK);
-    public static final IpProtocol IP_PROTO_ISO_IP = new IpProtocol(IP_PROTO_NUM_ISO_IP);
-    public static final IpProtocol IP_PROTO_VMTP = new IpProtocol(IP_PROTO_NUM_VMTP);
-    public static final IpProtocol IP_PROTO_SECURE_VMTP = new IpProtocol(IP_PROTO_NUM_SECURE_VMTP);
-    public static final IpProtocol IP_PROTO_VINES = new IpProtocol(IP_PROTO_NUM_VINES);
-    public static final IpProtocol IP_PROTO_TTP_IPTM = new IpProtocol(IP_PROTO_NUM_TTP_IPTM);
-    public static final IpProtocol IP_PROTO_NSFNET_IGP = new IpProtocol(IP_PROTO_NUM_NSFNET_IGP);
-    public static final IpProtocol IP_PROTO_DGP = new IpProtocol(IP_PROTO_NUM_DGP);
-    public static final IpProtocol IP_PROTO_TCF = new IpProtocol(IP_PROTO_NUM_TCF);
-    public static final IpProtocol IP_PROTO_EIGRP = new IpProtocol(IP_PROTO_NUM_EIGRP);
-    public static final IpProtocol IP_PROTO_OSPF = new IpProtocol(IP_PROTO_NUM_OSPF);
-    public static final IpProtocol IP_PROTO_Sprite_RPC = new IpProtocol(IP_PROTO_NUM_Sprite_RPC);
-    public static final IpProtocol IP_PROTO_LARP = new IpProtocol(IP_PROTO_NUM_LARP);
-    public static final IpProtocol IP_PROTO_MTP = new IpProtocol(IP_PROTO_NUM_MTP);
-    public static final IpProtocol IP_PROTO_AX_25 = new IpProtocol(IP_PROTO_NUM_AX_25);
-    public static final IpProtocol IP_PROTO_IPIP = new IpProtocol(IP_PROTO_NUM_IPIP);
-    public static final IpProtocol IP_PROTO_MICP = new IpProtocol(IP_PROTO_NUM_MICP);
-    public static final IpProtocol IP_PROTO_SCC_SP = new IpProtocol(IP_PROTO_NUM_SCC_SP);
-    public static final IpProtocol IP_PROTO_ETHERIP = new IpProtocol(IP_PROTO_NUM_ETHERIP);
-    public static final IpProtocol IP_PROTO_ENCAP = new IpProtocol(IP_PROTO_NUM_ENCAP);
-    public static final IpProtocol IP_PROTO_PRIVATE_ENCRYPT = new IpProtocol(IP_PROTO_NUM_PRIVATE_ENCRYPT);
-    public static final IpProtocol IP_PROTO_GMTP = new IpProtocol(IP_PROTO_NUM_GMTP);
-    public static final IpProtocol IP_PROTO_IFMP = new IpProtocol(IP_PROTO_NUM_IFMP);
-    public static final IpProtocol IP_PROTO_PNNI = new IpProtocol(IP_PROTO_NUM_PNNI);
-    public static final IpProtocol IP_PROTO_PIM = new IpProtocol(IP_PROTO_NUM_PIM);
-    public static final IpProtocol IP_PROTO_ARIS = new IpProtocol(IP_PROTO_NUM_ARIS);
-    public static final IpProtocol IP_PROTO_SCPS = new IpProtocol(IP_PROTO_NUM_SCPS);
-    public static final IpProtocol IP_PROTO_QNX = new IpProtocol(IP_PROTO_NUM_QNX);
-    public static final IpProtocol IP_PROTO_A_N = new IpProtocol(IP_PROTO_NUM_A_N);
-    public static final IpProtocol IP_PROTO_IP_COMP = new IpProtocol(IP_PROTO_NUM_IP_COMP);
-    public static final IpProtocol IP_PROTO_SNP = new IpProtocol(IP_PROTO_NUM_SNP);
-    public static final IpProtocol IP_PROTO_COMPAQ_PEER = new IpProtocol(IP_PROTO_NUM_COMPAQ_PEER);
-    public static final IpProtocol IP_PROTO_IPX_IN_IP = new IpProtocol(IP_PROTO_NUM_IPX_IN_IP);
-    public static final IpProtocol IP_PROTO_VRRP = new IpProtocol(IP_PROTO_NUM_VRRP);
-    public static final IpProtocol IP_PROTO_PGM = new IpProtocol(IP_PROTO_NUM_PGM);
-    public static final IpProtocol IP_PROTO_ZERO_HOP = new IpProtocol(IP_PROTO_NUM_ZERO_HOP);
-    public static final IpProtocol IP_PROTO_L2TP = new IpProtocol(IP_PROTO_NUM_L2TP);
-    public static final IpProtocol IP_PROTO_DDX = new IpProtocol(IP_PROTO_NUM_DDX);
-    public static final IpProtocol IP_PROTO_IATP = new IpProtocol(IP_PROTO_NUM_IATP);
-    public static final IpProtocol IP_PROTO_STP = new IpProtocol(IP_PROTO_NUM_STP);
-    public static final IpProtocol IP_PROTO_SRP = new IpProtocol(IP_PROTO_NUM_SRP);
-    public static final IpProtocol IP_PROTO_UTI = new IpProtocol(IP_PROTO_NUM_UTI);
-    public static final IpProtocol IP_PROTO_SMP = new IpProtocol(IP_PROTO_NUM_SMP);
-    public static final IpProtocol IP_PROTO_SM = new IpProtocol(IP_PROTO_NUM_SM);
-    public static final IpProtocol IP_PROTO_PTP = new IpProtocol(IP_PROTO_NUM_PTP);
-    public static final IpProtocol IP_PROTO_IS_IS_OVER_IPv4 = new IpProtocol(IP_PROTO_NUM_IS_IS_OVER_IPv4);
-    public static final IpProtocol IP_PROTO_FIRE = new IpProtocol(IP_PROTO_NUM_FIRE);
-    public static final IpProtocol IP_PROTO_CRTP = new IpProtocol(IP_PROTO_NUM_CRTP);
-    public static final IpProtocol IP_PROTO_CRUDP = new IpProtocol(IP_PROTO_NUM_CRUDP);
-    public static final IpProtocol IP_PROTO_SSCOPMCE = new IpProtocol(IP_PROTO_NUM_SSCOPMCE);
-    public static final IpProtocol IP_PROTO_IPLT = new IpProtocol(IP_PROTO_NUM_IPLT);
-    public static final IpProtocol IP_PROTO_SPS = new IpProtocol(IP_PROTO_NUM_SPS);
-    public static final IpProtocol IP_PROTO_PIPE = new IpProtocol(IP_PROTO_NUM_PIPE);
-    public static final IpProtocol IP_PROTO_SCTP = new IpProtocol(IP_PROTO_NUM_SCTP);
-    public static final IpProtocol IP_PROTO_FC = new IpProtocol(IP_PROTO_NUM_FC);
-    public static final IpProtocol IP_PROTO_RSVP_E2E_IGNORE = new IpProtocol(IP_PROTO_NUM_RSVP_E2E_IGNORE);
-    public static final IpProtocol IP_PROTO_MOBILITY_HEADER = new IpProtocol(IP_PROTO_NUM_MOBILITY_HEADER);
-    public static final IpProtocol IP_PROTO_UDP_LITE = new IpProtocol(IP_PROTO_NUM_UDP_LITE);
-    public static final IpProtocol IP_PROTO_MPLS_IN_IP = new IpProtocol(IP_PROTO_NUM_MPLS_IN_IP);
-    public static final IpProtocol IP_PROTO_MANET = new IpProtocol(IP_PROTO_NUM_MANET);
-    public static final IpProtocol IP_PROTO_HIP = new IpProtocol(IP_PROTO_NUM_HIP);
-    public static final IpProtocol IP_PROTO_SHIM6 = new IpProtocol(IP_PROTO_NUM_SHIM6);
+    public static final IpProtocol HOPOPT = new IpProtocol(NUM_HOPOPT);
+    public static final IpProtocol ICMP = new IpProtocol(NUM_ICMP);
+    public static final IpProtocol IGMP = new IpProtocol(NUM_IGMP);
+    public static final IpProtocol GGP = new IpProtocol(NUM_GGP);
+    public static final IpProtocol IPv4 = new IpProtocol(NUM_IPv4);
+    public static final IpProtocol ST = new IpProtocol(NUM_ST);
+    public static final IpProtocol TCP = new IpProtocol(NUM_TCP);
+    public static final IpProtocol CBT = new IpProtocol(NUM_CBT);
+    public static final IpProtocol EGP = new IpProtocol(NUM_EGP);
+    public static final IpProtocol IGP = new IpProtocol(NUM_IGP);
+    public static final IpProtocol BBN_RCC_MON = new IpProtocol(NUM_BBN_RCC_MON);
+    public static final IpProtocol NVP_II = new IpProtocol(NUM_NVP_II);
+    public static final IpProtocol PUP = new IpProtocol(NUM_PUP);
+    public static final IpProtocol ARGUS = new IpProtocol(NUM_ARGUS);
+    public static final IpProtocol EMCON = new IpProtocol(NUM_EMCON);
+    public static final IpProtocol XNET = new IpProtocol(NUM_XNET);
+    public static final IpProtocol CHAOS = new IpProtocol(NUM_CHAOS);
+    public static final IpProtocol UDP = new IpProtocol(NUM_UDP);
+    public static final IpProtocol MUX = new IpProtocol(NUM_MUX);
+    public static final IpProtocol DCN_MEAS = new IpProtocol(NUM_DCN_MEAS);
+    public static final IpProtocol HMP = new IpProtocol(NUM_HMP);
+    public static final IpProtocol PRM = new IpProtocol(NUM_PRM);
+    public static final IpProtocol XNS_IDP = new IpProtocol(NUM_XNS_IDP);
+    public static final IpProtocol TRUNK_1 = new IpProtocol(NUM_TRUNK_1);
+    public static final IpProtocol TRUNK_2 = new IpProtocol(NUM_TRUNK_2);
+    public static final IpProtocol LEAF_1 = new IpProtocol(NUM_LEAF_1);
+    public static final IpProtocol LEAF_2 = new IpProtocol(NUM_LEAF_2);
+    public static final IpProtocol RDP = new IpProtocol(NUM_RDP);
+    public static final IpProtocol IRTP = new IpProtocol(NUM_IRTP);
+    public static final IpProtocol ISO_TP4 = new IpProtocol(NUM_ISO_TP4);
+    public static final IpProtocol NETBLT = new IpProtocol(NUM_NETBLT);
+    public static final IpProtocol MFE_NSP = new IpProtocol(NUM_MFE_NSP);
+    public static final IpProtocol MERIT_INP = new IpProtocol(NUM_MERIT_INP);
+    public static final IpProtocol DCCP = new IpProtocol(NUM_DCCP);
+    public static final IpProtocol _3PC = new IpProtocol(NUM_3PC);
+    public static final IpProtocol IDPR = new IpProtocol(NUM_IDPR);
+    public static final IpProtocol XTP = new IpProtocol(NUM_XTP);
+    public static final IpProtocol DDP = new IpProtocol(NUM_DDP);
+    public static final IpProtocol IDPR_CMTP = new IpProtocol(NUM_IDPR_CMTP);
+    public static final IpProtocol TP_PP = new IpProtocol(NUM_TP_PP);
+    public static final IpProtocol IL = new IpProtocol(NUM_IL);
+    public static final IpProtocol IPv6 = new IpProtocol(NUM_IPv6);
+    public static final IpProtocol SDRP = new IpProtocol(NUM_SDRP);
+    public static final IpProtocol IPv6_ROUTE = new IpProtocol(NUM_IPv6_ROUTE);
+    public static final IpProtocol IPv6_FRAG = new IpProtocol(NUM_IPv6_FRAG);
+    public static final IpProtocol IDRP = new IpProtocol(NUM_IDRP);
+    public static final IpProtocol RSVP = new IpProtocol(NUM_RSVP);
+    public static final IpProtocol GRE = new IpProtocol(NUM_GRE);
+    public static final IpProtocol MHRP = new IpProtocol(NUM_MHRP);
+    public static final IpProtocol BNA = new IpProtocol(NUM_BNA);
+    public static final IpProtocol ESP = new IpProtocol(NUM_ESP);
+    public static final IpProtocol AH = new IpProtocol(NUM_AH);
+    public static final IpProtocol I_NLSP = new IpProtocol(NUM_I_NLSP);
+    public static final IpProtocol SWIPE = new IpProtocol(NUM_SWIPE);
+    public static final IpProtocol NARP = new IpProtocol(NUM_NARP);
+    public static final IpProtocol MOBILE = new IpProtocol(NUM_MOBILE);
+    public static final IpProtocol TLSP = new IpProtocol(NUM_TLSP);
+    public static final IpProtocol SKIP = new IpProtocol(NUM_SKIP);
+    public static final IpProtocol IPv6_ICMP = new IpProtocol(NUM_IPv6_ICMP);
+    public static final IpProtocol IPv6_NO_NXT = new IpProtocol(NUM_IPv6_NO_NXT);
+    public static final IpProtocol IPv6_OPTS = new IpProtocol(NUM_IPv6_OPTS);
+    public static final IpProtocol HOST_INTERNAL = new IpProtocol(NUM_HOST_INTERNAL);
+    public static final IpProtocol CFTP = new IpProtocol(NUM_CFTP);
+    public static final IpProtocol LOCAL_NET = new IpProtocol(NUM_LOCAL_NET);
+    public static final IpProtocol SAT_EXPAK = new IpProtocol(NUM_SAT_EXPAK);
+    public static final IpProtocol KRYPTOLAN = new IpProtocol(NUM_KRYPTOLAN);
+    public static final IpProtocol RVD = new IpProtocol(NUM_RVD);
+    public static final IpProtocol IPPC = new IpProtocol(NUM_IPPC);
+    public static final IpProtocol DIST_FS = new IpProtocol(NUM_DIST_FS);
+    public static final IpProtocol SAT_MON = new IpProtocol(NUM_SAT_MON);
+    public static final IpProtocol VISA = new IpProtocol(NUM_VISA);
+    public static final IpProtocol IPCV = new IpProtocol(NUM_IPCV);
+    public static final IpProtocol CPNX = new IpProtocol(NUM_CPNX);
+    public static final IpProtocol CPHB = new IpProtocol(NUM_CPHB);
+    public static final IpProtocol WSN = new IpProtocol(NUM_WSN);
+    public static final IpProtocol PVP = new IpProtocol(NUM_PVP);
+    public static final IpProtocol BR_SAT_MON = new IpProtocol(NUM_BR_SAT_MON);
+    public static final IpProtocol SUN_ND = new IpProtocol(NUM_SUN_ND);
+    public static final IpProtocol WB_MON = new IpProtocol(NUM_WB_MON);
+    public static final IpProtocol WB_EXPAK = new IpProtocol(NUM_WB_EXPAK);
+    public static final IpProtocol ISO_IP = new IpProtocol(NUM_ISO_IP);
+    public static final IpProtocol VMTP = new IpProtocol(NUM_VMTP);
+    public static final IpProtocol SECURE_VMTP = new IpProtocol(NUM_SECURE_VMTP);
+    public static final IpProtocol VINES = new IpProtocol(NUM_VINES);
+    public static final IpProtocol TTP_IPTM = new IpProtocol(NUM_TTP_IPTM);
+    public static final IpProtocol NSFNET_IGP = new IpProtocol(NUM_NSFNET_IGP);
+    public static final IpProtocol DGP = new IpProtocol(NUM_DGP);
+    public static final IpProtocol TCF = new IpProtocol(NUM_TCF);
+    public static final IpProtocol EIGRP = new IpProtocol(NUM_EIGRP);
+    public static final IpProtocol OSPF = new IpProtocol(NUM_OSPF);
+    public static final IpProtocol Sprite_RPC = new IpProtocol(NUM_Sprite_RPC);
+    public static final IpProtocol LARP = new IpProtocol(NUM_LARP);
+    public static final IpProtocol MTP = new IpProtocol(NUM_MTP);
+    public static final IpProtocol AX_25 = new IpProtocol(NUM_AX_25);
+    public static final IpProtocol IPIP = new IpProtocol(NUM_IPIP);
+    public static final IpProtocol MICP = new IpProtocol(NUM_MICP);
+    public static final IpProtocol SCC_SP = new IpProtocol(NUM_SCC_SP);
+    public static final IpProtocol ETHERIP = new IpProtocol(NUM_ETHERIP);
+    public static final IpProtocol ENCAP = new IpProtocol(NUM_ENCAP);
+    public static final IpProtocol PRIVATE_ENCRYPT = new IpProtocol(NUM_PRIVATE_ENCRYPT);
+    public static final IpProtocol GMTP = new IpProtocol(NUM_GMTP);
+    public static final IpProtocol IFMP = new IpProtocol(NUM_IFMP);
+    public static final IpProtocol PNNI = new IpProtocol(NUM_PNNI);
+    public static final IpProtocol PIM = new IpProtocol(NUM_PIM);
+    public static final IpProtocol ARIS = new IpProtocol(NUM_ARIS);
+    public static final IpProtocol SCPS = new IpProtocol(NUM_SCPS);
+    public static final IpProtocol QNX = new IpProtocol(NUM_QNX);
+    public static final IpProtocol A_N = new IpProtocol(NUM_A_N);
+    public static final IpProtocol IP_COMP = new IpProtocol(NUM_IP_COMP);
+    public static final IpProtocol SNP = new IpProtocol(NUM_SNP);
+    public static final IpProtocol COMPAQ_PEER = new IpProtocol(NUM_COMPAQ_PEER);
+    public static final IpProtocol IPX_IN_IP = new IpProtocol(NUM_IPX_IN_IP);
+    public static final IpProtocol VRRP = new IpProtocol(NUM_VRRP);
+    public static final IpProtocol PGM = new IpProtocol(NUM_PGM);
+    public static final IpProtocol ZERO_HOP = new IpProtocol(NUM_ZERO_HOP);
+    public static final IpProtocol L2TP = new IpProtocol(NUM_L2TP);
+    public static final IpProtocol DDX = new IpProtocol(NUM_DDX);
+    public static final IpProtocol IATP = new IpProtocol(NUM_IATP);
+    public static final IpProtocol STP = new IpProtocol(NUM_STP);
+    public static final IpProtocol SRP = new IpProtocol(NUM_SRP);
+    public static final IpProtocol UTI = new IpProtocol(NUM_UTI);
+    public static final IpProtocol SMP = new IpProtocol(NUM_SMP);
+    public static final IpProtocol SM = new IpProtocol(NUM_SM);
+    public static final IpProtocol PTP = new IpProtocol(NUM_PTP);
+    public static final IpProtocol IS_IS_OVER_IPv4 = new IpProtocol(NUM_IS_IS_OVER_IPv4);
+    public static final IpProtocol FIRE = new IpProtocol(NUM_FIRE);
+    public static final IpProtocol CRTP = new IpProtocol(NUM_CRTP);
+    public static final IpProtocol CRUDP = new IpProtocol(NUM_CRUDP);
+    public static final IpProtocol SSCOPMCE = new IpProtocol(NUM_SSCOPMCE);
+    public static final IpProtocol IPLT = new IpProtocol(NUM_IPLT);
+    public static final IpProtocol SPS = new IpProtocol(NUM_SPS);
+    public static final IpProtocol PIPE = new IpProtocol(NUM_PIPE);
+    public static final IpProtocol SCTP = new IpProtocol(NUM_SCTP);
+    public static final IpProtocol FC = new IpProtocol(NUM_FC);
+    public static final IpProtocol RSVP_E2E_IGNORE = new IpProtocol(NUM_RSVP_E2E_IGNORE);
+    public static final IpProtocol MOBILITY_HEADER = new IpProtocol(NUM_MOBILITY_HEADER);
+    public static final IpProtocol UDP_LITE = new IpProtocol(NUM_UDP_LITE);
+    public static final IpProtocol MPLS_IN_IP = new IpProtocol(NUM_MPLS_IN_IP);
+    public static final IpProtocol MANET = new IpProtocol(NUM_MANET);
+    public static final IpProtocol HIP = new IpProtocol(NUM_HIP);
+    public static final IpProtocol SHIM6 = new IpProtocol(NUM_SHIM6);
 
-    public static final IpProtocol NONE = IP_PROTO_HOPOPT;
+    public static final IpProtocol NONE = HOPOPT;
 
-    public static final IpProtocol NO_MASK = IP_PROTO_HOPOPT;
+    public static final IpProtocol NO_MASK = HOPOPT;
     public static final IpProtocol FULL_MASK = new IpProtocol((short)0x0000);
 
     private IpProtocol(short version) {
@@ -317,288 +318,288 @@
 
     public static IpProtocol of(short proto) {
         switch (proto) {
-            case IP_PROTO_NUM_HOPOPT:
-                return IP_PROTO_HOPOPT;
-            case IP_PROTO_NUM_ICMP:
-                return IP_PROTO_ICMP;
-            case IP_PROTO_NUM_IGMP:
-                return IP_PROTO_IGMP;
-            case IP_PROTO_NUM_GGP:
-                return IP_PROTO_GGP;
-            case IP_PROTO_NUM_IPv4:
-                return IP_PROTO_IPv4;
-            case IP_PROTO_NUM_ST:
-                return IP_PROTO_ST;
-            case IP_PROTO_NUM_TCP:
-                return IP_PROTO_TCP;
-            case IP_PROTO_NUM_CBT:
-                return IP_PROTO_CBT;
-            case IP_PROTO_NUM_EGP:
-                return IP_PROTO_EGP;
-            case IP_PROTO_NUM_IGP:
-                return IP_PROTO_IGP;
-            case IP_PROTO_NUM_BBN_RCC_MON:
-                return IP_PROTO_BBN_RCC_MON;
-            case IP_PROTO_NUM_NVP_II:
-                return IP_PROTO_NVP_II;
-            case IP_PROTO_NUM_PUP:
-                return IP_PROTO_PUP;
-            case IP_PROTO_NUM_ARGUS:
-                return IP_PROTO_ARGUS;
-            case IP_PROTO_NUM_EMCON:
-                return IP_PROTO_EMCON;
-            case IP_PROTO_NUM_XNET:
-                return IP_PROTO_XNET;
-            case IP_PROTO_NUM_CHAOS:
-                return IP_PROTO_CHAOS;
-            case IP_PROTO_NUM_UDP:
-                return IP_PROTO_UDP;
-            case IP_PROTO_NUM_MUX:
-                return IP_PROTO_MUX;
-            case IP_PROTO_NUM_DCN_MEAS:
-                return IP_PROTO_DCN_MEAS;
-            case IP_PROTO_NUM_HMP:
-                return IP_PROTO_HMP;
-            case IP_PROTO_NUM_PRM:
-                return IP_PROTO_PRM;
-            case IP_PROTO_NUM_XNS_IDP:
-                return IP_PROTO_XNS_IDP;
-            case IP_PROTO_NUM_TRUNK_1:
-                return IP_PROTO_TRUNK_1;
-            case IP_PROTO_NUM_TRUNK_2:
-                return IP_PROTO_TRUNK_2;
-            case IP_PROTO_NUM_LEAF_1:
-                return IP_PROTO_LEAF_1;
-            case IP_PROTO_NUM_LEAF_2:
-                return IP_PROTO_LEAF_2;
-            case IP_PROTO_NUM_RDP:
-                return IP_PROTO_RDP;
-            case IP_PROTO_NUM_IRTP:
-                return IP_PROTO_IRTP;
-            case IP_PROTO_NUM_ISO_TP4:
-                return IP_PROTO_ISO_TP4;
-            case IP_PROTO_NUM_NETBLT:
-                return IP_PROTO_NETBLT;
-            case IP_PROTO_NUM_MFE_NSP:
-                return IP_PROTO_MFE_NSP;
-            case IP_PROTO_NUM_MERIT_INP:
-                return IP_PROTO_MERIT_INP;
-            case IP_PROTO_NUM_DCCP:
-                return IP_PROTO_DCCP;
-            case IP_PROTO_NUM_3PC:
-                return IP_PROTO_3PC;
-            case IP_PROTO_NUM_IDPR:
-                return IP_PROTO_IDPR;
-            case IP_PROTO_NUM_XTP:
-                return IP_PROTO_XTP;
-            case IP_PROTO_NUM_DDP:
-                return IP_PROTO_DDP;
-            case IP_PROTO_NUM_IDPR_CMTP:
-                return IP_PROTO_IDPR_CMTP;
-            case IP_PROTO_NUM_TP_PP:
-                return IP_PROTO_TP_PP;
-            case IP_PROTO_NUM_IL:
-                return IP_PROTO_IL;
-            case IP_PROTO_NUM_IPv6:
-                return IP_PROTO_IPv6;
-            case IP_PROTO_NUM_SDRP:
-                return IP_PROTO_SDRP;
-            case IP_PROTO_NUM_IPv6_ROUTE:
-                return IP_PROTO_IPv6_ROUTE;
-            case IP_PROTO_NUM_IPv6_FRAG:
-                return IP_PROTO_IPv6_FRAG;
-            case IP_PROTO_NUM_IDRP:
-                return IP_PROTO_IDRP;
-            case IP_PROTO_NUM_RSVP:
-                return IP_PROTO_RSVP;
-            case IP_PROTO_NUM_GRE:
-                return IP_PROTO_GRE;
-            case IP_PROTO_NUM_MHRP:
-                return IP_PROTO_MHRP;
-            case IP_PROTO_NUM_BNA:
-                return IP_PROTO_BNA;
-            case IP_PROTO_NUM_ESP:
-                return IP_PROTO_ESP;
-            case IP_PROTO_NUM_AH:
-                return IP_PROTO_AH;
-            case IP_PROTO_NUM_I_NLSP:
-                return IP_PROTO_I_NLSP;
-            case IP_PROTO_NUM_SWIPE:
-                return IP_PROTO_SWIPE;
-            case IP_PROTO_NUM_NARP:
-                return IP_PROTO_NARP;
-            case IP_PROTO_NUM_MOBILE:
-                return IP_PROTO_MOBILE;
-            case IP_PROTO_NUM_TLSP:
-                return IP_PROTO_TLSP;
-            case IP_PROTO_NUM_SKIP:
-                return IP_PROTO_SKIP;
-            case IP_PROTO_NUM_IPv6_ICMP:
-                return IP_PROTO_IPv6_ICMP;
-            case IP_PROTO_NUM_IPv6_NO_NXT:
-                return IP_PROTO_IPv6_NO_NXT;
-            case IP_PROTO_NUM_IPv6_OPTS:
-                return IP_PROTO_IPv6_OPTS;
-            case IP_PROTO_NUM_HOST_INTERNAL:
-                return IP_PROTO_HOST_INTERNAL;
-            case IP_PROTO_NUM_CFTP:
-                return IP_PROTO_CFTP;
-            case IP_PROTO_NUM_LOCAL_NET:
-                return IP_PROTO_LOCAL_NET;
-            case IP_PROTO_NUM_SAT_EXPAK:
-                return IP_PROTO_SAT_EXPAK;
-            case IP_PROTO_NUM_KRYPTOLAN:
-                return IP_PROTO_KRYPTOLAN;
-            case IP_PROTO_NUM_RVD:
-                return IP_PROTO_RVD;
-            case IP_PROTO_NUM_IPPC:
-                return IP_PROTO_IPPC;
-            case IP_PROTO_NUM_DIST_FS:
-                return IP_PROTO_DIST_FS;
-            case IP_PROTO_NUM_SAT_MON:
-                return IP_PROTO_SAT_MON;
-            case IP_PROTO_NUM_VISA:
-                return IP_PROTO_VISA;
-            case IP_PROTO_NUM_IPCV:
-                return IP_PROTO_IPCV;
-            case IP_PROTO_NUM_CPNX:
-                return IP_PROTO_CPNX;
-            case IP_PROTO_NUM_CPHB:
-                return IP_PROTO_CPHB;
-            case IP_PROTO_NUM_WSN:
-                return IP_PROTO_WSN;
-            case IP_PROTO_NUM_PVP:
-                return IP_PROTO_PVP;
-            case IP_PROTO_NUM_BR_SAT_MON:
-                return IP_PROTO_BR_SAT_MON;
-            case IP_PROTO_NUM_SUN_ND:
-                return IP_PROTO_SUN_ND;
-            case IP_PROTO_NUM_WB_MON:
-                return IP_PROTO_WB_MON;
-            case IP_PROTO_NUM_WB_EXPAK:
-                return IP_PROTO_WB_EXPAK;
-            case IP_PROTO_NUM_ISO_IP:
-                return IP_PROTO_ISO_IP;
-            case IP_PROTO_NUM_VMTP:
-                return IP_PROTO_VMTP;
-            case IP_PROTO_NUM_SECURE_VMTP:
-                return IP_PROTO_SECURE_VMTP;
-            case IP_PROTO_NUM_VINES:
-                return IP_PROTO_VINES;
-            case IP_PROTO_NUM_TTP_IPTM:
-                return IP_PROTO_TTP_IPTM;
-            case IP_PROTO_NUM_NSFNET_IGP:
-                return IP_PROTO_NSFNET_IGP;
-            case IP_PROTO_NUM_DGP:
-                return IP_PROTO_DGP;
-            case IP_PROTO_NUM_TCF:
-                return IP_PROTO_TCF;
-            case IP_PROTO_NUM_EIGRP:
-                return IP_PROTO_EIGRP;
-            case IP_PROTO_NUM_OSPF:
-                return IP_PROTO_OSPF;
-            case IP_PROTO_NUM_Sprite_RPC:
-                return IP_PROTO_Sprite_RPC;
-            case IP_PROTO_NUM_LARP:
-                return IP_PROTO_LARP;
-            case IP_PROTO_NUM_MTP:
-                return IP_PROTO_MTP;
-            case IP_PROTO_NUM_AX_25:
-                return IP_PROTO_AX_25;
-            case IP_PROTO_NUM_IPIP:
-                return IP_PROTO_IPIP;
-            case IP_PROTO_NUM_MICP:
-                return IP_PROTO_MICP;
-            case IP_PROTO_NUM_SCC_SP:
-                return IP_PROTO_SCC_SP;
-            case IP_PROTO_NUM_ETHERIP:
-                return IP_PROTO_ETHERIP;
-            case IP_PROTO_NUM_ENCAP:
-                return IP_PROTO_ENCAP;
-            case IP_PROTO_NUM_PRIVATE_ENCRYPT:
-                return IP_PROTO_PRIVATE_ENCRYPT;
-            case IP_PROTO_NUM_GMTP:
-                return IP_PROTO_GMTP;
-            case IP_PROTO_NUM_IFMP:
-                return IP_PROTO_IFMP;
-            case IP_PROTO_NUM_PNNI:
-                return IP_PROTO_PNNI;
-            case IP_PROTO_NUM_PIM:
-                return IP_PROTO_PIM;
-            case IP_PROTO_NUM_ARIS:
-                return IP_PROTO_ARIS;
-            case IP_PROTO_NUM_SCPS:
-                return IP_PROTO_SCPS;
-            case IP_PROTO_NUM_QNX:
-                return IP_PROTO_QNX;
-            case IP_PROTO_NUM_A_N:
-                return IP_PROTO_A_N;
-            case IP_PROTO_NUM_IP_COMP:
-                return IP_PROTO_IP_COMP;
-            case IP_PROTO_NUM_SNP:
-                return IP_PROTO_SNP;
-            case IP_PROTO_NUM_COMPAQ_PEER:
-                return IP_PROTO_COMPAQ_PEER;
-            case IP_PROTO_NUM_IPX_IN_IP:
-                return IP_PROTO_IPX_IN_IP;
-            case IP_PROTO_NUM_VRRP:
-                return IP_PROTO_VRRP;
-            case IP_PROTO_NUM_PGM:
-                return IP_PROTO_PGM;
-            case IP_PROTO_NUM_ZERO_HOP:
-                return IP_PROTO_ZERO_HOP;
-            case IP_PROTO_NUM_L2TP:
-                return IP_PROTO_L2TP;
-            case IP_PROTO_NUM_DDX:
-                return IP_PROTO_DDX;
-            case IP_PROTO_NUM_IATP:
-                return IP_PROTO_IATP;
-            case IP_PROTO_NUM_STP:
-                return IP_PROTO_STP;
-            case IP_PROTO_NUM_SRP:
-                return IP_PROTO_SRP;
-            case IP_PROTO_NUM_UTI:
-                return IP_PROTO_UTI;
-            case IP_PROTO_NUM_SMP:
-                return IP_PROTO_SMP;
-            case IP_PROTO_NUM_SM:
-                return IP_PROTO_SM;
-            case IP_PROTO_NUM_PTP:
-                return IP_PROTO_PTP;
-            case IP_PROTO_NUM_IS_IS_OVER_IPv4:
-                return IP_PROTO_IS_IS_OVER_IPv4;
-            case IP_PROTO_NUM_FIRE:
-                return IP_PROTO_FIRE;
-            case IP_PROTO_NUM_CRTP:
-                return IP_PROTO_CRTP;
-            case IP_PROTO_NUM_CRUDP:
-                return IP_PROTO_CRUDP;
-            case IP_PROTO_NUM_SSCOPMCE:
-                return IP_PROTO_SSCOPMCE;
-            case IP_PROTO_NUM_IPLT:
-                return IP_PROTO_IPLT;
-            case IP_PROTO_NUM_SPS:
-                return IP_PROTO_SPS;
-            case IP_PROTO_NUM_PIPE:
-                return IP_PROTO_PIPE;
-            case IP_PROTO_NUM_SCTP:
-                return IP_PROTO_SCTP;
-            case IP_PROTO_NUM_FC:
-                return IP_PROTO_FC;
-            case IP_PROTO_NUM_RSVP_E2E_IGNORE:
-                return IP_PROTO_RSVP_E2E_IGNORE;
-            case IP_PROTO_NUM_MOBILITY_HEADER:
-                return IP_PROTO_MOBILITY_HEADER;
-            case IP_PROTO_NUM_UDP_LITE:
-                return IP_PROTO_UDP_LITE;
-            case IP_PROTO_NUM_MPLS_IN_IP:
-                return IP_PROTO_MPLS_IN_IP;
-            case IP_PROTO_NUM_MANET:
-                return IP_PROTO_MANET;
-            case IP_PROTO_NUM_HIP:
-                return IP_PROTO_HIP;
-            case IP_PROTO_NUM_SHIM6:
-                return IP_PROTO_SHIM6;
+            case NUM_HOPOPT:
+                return HOPOPT;
+            case NUM_ICMP:
+                return ICMP;
+            case NUM_IGMP:
+                return IGMP;
+            case NUM_GGP:
+                return GGP;
+            case NUM_IPv4:
+                return IPv4;
+            case NUM_ST:
+                return ST;
+            case NUM_TCP:
+                return TCP;
+            case NUM_CBT:
+                return CBT;
+            case NUM_EGP:
+                return EGP;
+            case NUM_IGP:
+                return IGP;
+            case NUM_BBN_RCC_MON:
+                return BBN_RCC_MON;
+            case NUM_NVP_II:
+                return NVP_II;
+            case NUM_PUP:
+                return PUP;
+            case NUM_ARGUS:
+                return ARGUS;
+            case NUM_EMCON:
+                return EMCON;
+            case NUM_XNET:
+                return XNET;
+            case NUM_CHAOS:
+                return CHAOS;
+            case NUM_UDP:
+                return UDP;
+            case NUM_MUX:
+                return MUX;
+            case NUM_DCN_MEAS:
+                return DCN_MEAS;
+            case NUM_HMP:
+                return HMP;
+            case NUM_PRM:
+                return PRM;
+            case NUM_XNS_IDP:
+                return XNS_IDP;
+            case NUM_TRUNK_1:
+                return TRUNK_1;
+            case NUM_TRUNK_2:
+                return TRUNK_2;
+            case NUM_LEAF_1:
+                return LEAF_1;
+            case NUM_LEAF_2:
+                return LEAF_2;
+            case NUM_RDP:
+                return RDP;
+            case NUM_IRTP:
+                return IRTP;
+            case NUM_ISO_TP4:
+                return ISO_TP4;
+            case NUM_NETBLT:
+                return NETBLT;
+            case NUM_MFE_NSP:
+                return MFE_NSP;
+            case NUM_MERIT_INP:
+                return MERIT_INP;
+            case NUM_DCCP:
+                return DCCP;
+            case NUM_3PC:
+                return _3PC;
+            case NUM_IDPR:
+                return IDPR;
+            case NUM_XTP:
+                return XTP;
+            case NUM_DDP:
+                return DDP;
+            case NUM_IDPR_CMTP:
+                return IDPR_CMTP;
+            case NUM_TP_PP:
+                return TP_PP;
+            case NUM_IL:
+                return IL;
+            case NUM_IPv6:
+                return IPv6;
+            case NUM_SDRP:
+                return SDRP;
+            case NUM_IPv6_ROUTE:
+                return IPv6_ROUTE;
+            case NUM_IPv6_FRAG:
+                return IPv6_FRAG;
+            case NUM_IDRP:
+                return IDRP;
+            case NUM_RSVP:
+                return RSVP;
+            case NUM_GRE:
+                return GRE;
+            case NUM_MHRP:
+                return MHRP;
+            case NUM_BNA:
+                return BNA;
+            case NUM_ESP:
+                return ESP;
+            case NUM_AH:
+                return AH;
+            case NUM_I_NLSP:
+                return I_NLSP;
+            case NUM_SWIPE:
+                return SWIPE;
+            case NUM_NARP:
+                return NARP;
+            case NUM_MOBILE:
+                return MOBILE;
+            case NUM_TLSP:
+                return TLSP;
+            case NUM_SKIP:
+                return SKIP;
+            case NUM_IPv6_ICMP:
+                return IPv6_ICMP;
+            case NUM_IPv6_NO_NXT:
+                return IPv6_NO_NXT;
+            case NUM_IPv6_OPTS:
+                return IPv6_OPTS;
+            case NUM_HOST_INTERNAL:
+                return HOST_INTERNAL;
+            case NUM_CFTP:
+                return CFTP;
+            case NUM_LOCAL_NET:
+                return LOCAL_NET;
+            case NUM_SAT_EXPAK:
+                return SAT_EXPAK;
+            case NUM_KRYPTOLAN:
+                return KRYPTOLAN;
+            case NUM_RVD:
+                return RVD;
+            case NUM_IPPC:
+                return IPPC;
+            case NUM_DIST_FS:
+                return DIST_FS;
+            case NUM_SAT_MON:
+                return SAT_MON;
+            case NUM_VISA:
+                return VISA;
+            case NUM_IPCV:
+                return IPCV;
+            case NUM_CPNX:
+                return CPNX;
+            case NUM_CPHB:
+                return CPHB;
+            case NUM_WSN:
+                return WSN;
+            case NUM_PVP:
+                return PVP;
+            case NUM_BR_SAT_MON:
+                return BR_SAT_MON;
+            case NUM_SUN_ND:
+                return SUN_ND;
+            case NUM_WB_MON:
+                return WB_MON;
+            case NUM_WB_EXPAK:
+                return WB_EXPAK;
+            case NUM_ISO_IP:
+                return ISO_IP;
+            case NUM_VMTP:
+                return VMTP;
+            case NUM_SECURE_VMTP:
+                return SECURE_VMTP;
+            case NUM_VINES:
+                return VINES;
+            case NUM_TTP_IPTM:
+                return TTP_IPTM;
+            case NUM_NSFNET_IGP:
+                return NSFNET_IGP;
+            case NUM_DGP:
+                return DGP;
+            case NUM_TCF:
+                return TCF;
+            case NUM_EIGRP:
+                return EIGRP;
+            case NUM_OSPF:
+                return OSPF;
+            case NUM_Sprite_RPC:
+                return Sprite_RPC;
+            case NUM_LARP:
+                return LARP;
+            case NUM_MTP:
+                return MTP;
+            case NUM_AX_25:
+                return AX_25;
+            case NUM_IPIP:
+                return IPIP;
+            case NUM_MICP:
+                return MICP;
+            case NUM_SCC_SP:
+                return SCC_SP;
+            case NUM_ETHERIP:
+                return ETHERIP;
+            case NUM_ENCAP:
+                return ENCAP;
+            case NUM_PRIVATE_ENCRYPT:
+                return PRIVATE_ENCRYPT;
+            case NUM_GMTP:
+                return GMTP;
+            case NUM_IFMP:
+                return IFMP;
+            case NUM_PNNI:
+                return PNNI;
+            case NUM_PIM:
+                return PIM;
+            case NUM_ARIS:
+                return ARIS;
+            case NUM_SCPS:
+                return SCPS;
+            case NUM_QNX:
+                return QNX;
+            case NUM_A_N:
+                return A_N;
+            case NUM_IP_COMP:
+                return IP_COMP;
+            case NUM_SNP:
+                return SNP;
+            case NUM_COMPAQ_PEER:
+                return COMPAQ_PEER;
+            case NUM_IPX_IN_IP:
+                return IPX_IN_IP;
+            case NUM_VRRP:
+                return VRRP;
+            case NUM_PGM:
+                return PGM;
+            case NUM_ZERO_HOP:
+                return ZERO_HOP;
+            case NUM_L2TP:
+                return L2TP;
+            case NUM_DDX:
+                return DDX;
+            case NUM_IATP:
+                return IATP;
+            case NUM_STP:
+                return STP;
+            case NUM_SRP:
+                return SRP;
+            case NUM_UTI:
+                return UTI;
+            case NUM_SMP:
+                return SMP;
+            case NUM_SM:
+                return SM;
+            case NUM_PTP:
+                return PTP;
+            case NUM_IS_IS_OVER_IPv4:
+                return IS_IS_OVER_IPv4;
+            case NUM_FIRE:
+                return FIRE;
+            case NUM_CRTP:
+                return CRTP;
+            case NUM_CRUDP:
+                return CRUDP;
+            case NUM_SSCOPMCE:
+                return SSCOPMCE;
+            case NUM_IPLT:
+                return IPLT;
+            case NUM_SPS:
+                return SPS;
+            case NUM_PIPE:
+                return PIPE;
+            case NUM_SCTP:
+                return SCTP;
+            case NUM_FC:
+                return FC;
+            case NUM_RSVP_E2E_IGNORE:
+                return RSVP_E2E_IGNORE;
+            case NUM_MOBILITY_HEADER:
+                return MOBILITY_HEADER;
+            case NUM_UDP_LITE:
+                return UDP_LITE;
+            case NUM_MPLS_IN_IP:
+                return MPLS_IN_IP;
+            case NUM_MANET:
+                return MANET;
+            case NUM_HIP:
+                return HIP;
+            case NUM_SHIM6:
+                return SHIM6;
             default:
                 if (proto >= MAX_PROTO) {
                     throw new IllegalArgumentException("Illegal IP protocol number: "
@@ -655,4 +656,10 @@
         return Shorts.compare(proto, o.proto);
     }
 
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putShort(proto);
+    }
+
 }
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
index b7f7f67..6d9421a 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
@@ -4,6 +4,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 @Immutable
@@ -11,6 +12,9 @@
     static final int LENGTH = 4;
     private final int rawValue;
 
+    private final static int NONE_VAL = 0;
+    public final static LagId NONE = new LagId(NONE_VAL);
+
     private LagId(final int rawValue) {
         this.rawValue = rawValue;
     }
@@ -72,4 +76,9 @@
     public LagId applyMask(LagId mask) {
         return LagId.of(rawValue & mask.rawValue);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(rawValue);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
index 87be7c2..aaa31eb 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
@@ -4,6 +4,7 @@
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 import org.projectfloodlight.openflow.util.HexString;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Longs;
 
 /**
@@ -19,6 +20,9 @@
     private final static long NONE_VAL = 0x0L;
     public static final MacAddress NONE = new MacAddress(NONE_VAL);
 
+    private final static long BROADCAST_VAL = 0x0000FFFFFFFFFFFFL;
+    public static final MacAddress BROADCAST = new MacAddress(BROADCAST_VAL);
+
     public static final MacAddress NO_MASK = MacAddress.of(0xFFFFFFFFFFFFFFFFl);
     public static final MacAddress FULL_MASK = MacAddress.of(0x0);
 
@@ -27,6 +31,9 @@
     }
 
     public static MacAddress of(final byte[] address) {
+        if (address.length != MacAddrLen)
+            throw new IllegalArgumentException(
+                    "Mac address byte array must be exactly 6 bytes long; length = " + address.length);
         long raw =
                 (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32
                         | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16
@@ -34,30 +41,36 @@
         return MacAddress.of(raw);
     }
 
-    public static MacAddress of(final long raw) {
+    public static MacAddress of(long raw) {
+        raw &= BROADCAST_VAL;
         if(raw == NONE_VAL)
             return NONE;
-
+        if (raw == BROADCAST_VAL)
+            return BROADCAST;
         return new MacAddress(raw);
     }
 
     public static MacAddress of(final String string) {
         int index = 0;
         int shift = 40;
+        final String FORMAT_ERROR = "Mac address is not well-formed. " +
+                "It must consist of 6 hex digit pairs separated by colons: ";
 
         long raw = 0;
         if (string.length() != 6 * 2 + 5)
-            throw new IllegalArgumentException("Mac address not well formed: " + string);
+            throw new IllegalArgumentException(FORMAT_ERROR + string);
 
         while (shift >= 0) {
-            raw |=
-                    ((long) (Character.digit(string.charAt(index++), 16) << 4 | Character
-                            .digit(string.charAt(index++), 16))) << shift;
+            int digit1 = Character.digit(string.charAt(index++), 16);
+            int digit2 = Character.digit(string.charAt(index++), 16);
+            if ((digit1 < 0) || (digit2 < 0))
+                throw new IllegalArgumentException(FORMAT_ERROR + string);
+            raw |= ((long) (digit1 << 4 | digit2)) << shift;
 
             if (shift == 0)
                 break;
             if (string.charAt(index++) != ':')
-                throw new IllegalArgumentException("Mac address not well formed: " + string);
+                throw new IllegalArgumentException(FORMAT_ERROR + string);
             shift -= 8;
         }
         return MacAddress.of(raw);
@@ -82,6 +95,25 @@
         return bytesCache;
     }
 
+    /**
+     * Returns {@code true} if the MAC address is the broadcast address.
+     * @return {@code true} if the MAC address is the broadcast address.
+     */
+    public boolean isBroadcast() {
+        return this == BROADCAST;
+    }
+
+    /**
+     * Returns {@code true} if the MAC address is a multicast address.
+     * @return {@code true} if the MAC address is a multicast address.
+     */
+    public boolean isMulticast() {
+        if (isBroadcast()) {
+            return false;
+        }
+        return (rawValue & (0x01L << 40)) != 0;
+    }
+
     @Override
     public int getLength() {
         return MacAddrLen;
@@ -138,6 +170,12 @@
         return Longs.compare(rawValue, o.rawValue);
     }
 
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt((int) (this.rawValue >> 16));
+        sink.putShort((short) (this.rawValue & 0xFFFF));
+    }
+
 
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java
index 4d88793..ea2317a 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java
@@ -1,5 +1,7 @@
 package org.projectfloodlight.openflow.types;
 
+import com.google.common.hash.PrimitiveSink;
+
 
 
 public class Masked<T extends OFValueType<T>> implements OFValueType<Masked<T>> {
@@ -66,4 +68,10 @@
         else
             return mask.compareTo(o.mask);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        value.putTo(sink);
+        mask.putTo(sink);
+    }
 }
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/Metadata.java
deleted file mode 100644
index 4764747..0000000
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.projectfloodlight.openflow.types;
-
-import javax.annotation.concurrent.Immutable;
-
-import com.google.common.primitives.UnsignedInts;
-
-@Immutable
-public class Metadata implements OFValueType<Metadata> {
-    static final int LENGTH = 4;
-
-    private final static int NONE_VAL = 0;
-    public final static Metadata NONE = new Metadata(NONE_VAL);
-
-    private final int rawValue;
-
-    private Metadata(final int rawValue) {
-        this.rawValue = rawValue;
-    }
-
-    public static Metadata of(final int raw) {
-        if(raw == NONE_VAL)
-            return NONE;
-
-        return new Metadata(raw);
-    }
-
-    public int getInt() {
-        return rawValue;
-    }
-
-    @Override
-    public int getLength() {
-        return LENGTH;
-    }
-
-    @Override
-    public String toString() {
-        return Integer.toString(rawValue);
-    }
-
-    @Override
-    public Metadata applyMask(Metadata mask) {
-        return Metadata.of(rawValue & mask.rawValue);    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + rawValue;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        Metadata other = (Metadata) obj;
-        if (rawValue != other.rawValue)
-            return false;
-        return true;
-    }
-
-    @Override
-    public int compareTo(Metadata o) {
-        return UnsignedInts.compare(rawValue, rawValue);
-    }
-}
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..5cec233
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
@@ -0,0 +1,100 @@
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import com.google.common.hash.PrimitiveSink;
+
+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);
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putLong(raw1);
+        sink.putLong(raw2);
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBooleanValue.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBooleanValue.java
new file mode 100644
index 0000000..b386e54
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBooleanValue.java
@@ -0,0 +1,107 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    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
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+import org.projectfloodlight.openflow.protocol.OFMessageReader;
+import org.projectfloodlight.openflow.protocol.Writeable;
+
+import com.google.common.hash.PrimitiveSink;
+
+public class OFBooleanValue implements Writeable, OFValueType<OFBooleanValue> {
+    public final static OFBooleanValue TRUE = new OFBooleanValue(true);
+    public final static OFBooleanValue FALSE = new OFBooleanValue(false);
+
+    private final boolean value;
+
+    private OFBooleanValue(boolean value) {
+      this.value = value;
+    }
+
+    public static OFBooleanValue of(boolean value) {
+      return value ? TRUE : FALSE;
+    }
+
+    public boolean getValue() {
+      return value;
+    }
+
+    public int getInt() {
+      return value ? 1 : 0;
+    }
+
+    @Override
+    public String toString() {
+        return "" + value;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + getInt();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        OFBooleanValue other = (OFBooleanValue) obj;
+        if (value != other.value)
+            return false;
+        return true;
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer bb) {
+        bb.writeByte(getInt());
+    }
+
+    private static class Reader implements OFMessageReader<OFBooleanValue> {
+        @Override
+        public OFBooleanValue readFrom(ChannelBuffer bb) throws OFParseError {
+            return of(bb.readByte() != 0);
+        }
+    }
+
+    @Override
+    public int getLength() {
+        return 1;
+    }
+
+    @Override
+    public OFBooleanValue applyMask(OFBooleanValue mask) {
+        return of(value && mask.value);
+    }
+
+    @Override
+    public int compareTo(OFBooleanValue o) {
+        return getInt() - o.getInt();
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putByte((byte)getInt());
+    }
+}
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..7f76b4d 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
@@ -1,9 +1,8 @@
 package org.projectfloodlight.openflow.types;
 
-import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.annotations.Immutable;
-import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 /**
@@ -12,7 +11,7 @@
  * @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
  */
 @Immutable
-public class OFBufferId implements Comparable<OFBufferId> {
+public class OFBufferId implements Comparable<OFBufferId>, PrimitiveSinkable {
     public static final OFBufferId NO_BUFFER = new OFBufferId(0xFFFFFFFF);
 
     private final int rawValue;
@@ -36,14 +35,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;
@@ -70,4 +61,9 @@
     public int compareTo(OFBufferId o) {
         return UnsignedInts.compare(rawValue, o.rawValue);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(rawValue);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java
new file mode 100644
index 0000000..b05d5fa
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java
@@ -0,0 +1,156 @@
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.annotations.Immutable;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Abstraction of an logical / OpenFlow group (ofp_group) in OpenFlow.
+ * Immutable.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+@Immutable
+public class OFGroup implements OFValueType<OFGroup> {
+    static final int LENGTH = 4;
+
+    // private int constants (OF1.1+) to avoid duplication in the code
+    // should not have to use these outside this class
+    private static final int ZERO_VAL = 0x00;
+    private static final int MAX_VAL = 0xffffff00;
+    private static final int ALL_VAL = 0xfffffffc;
+    private static final int ANY_VAL = 0xffffffff;
+
+
+    // ////////////// public constants - use to access well known OpenFlow group constants
+
+    /** Maximum number of physical and logical switch groups. */
+    public final static OFGroup MAX = new NamedGroup(MAX_VAL, "max");
+
+    /** All groups */
+    public final static OFGroup ALL = new NamedGroup(ALL_VAL, "all");
+
+    /**
+     * Wildcard group used only for flow mod (delete) and flow stats requests. */
+    public final static OFGroup ANY = new NamedGroup(ANY_VAL, "any");
+
+    /** group 0 in case we need it */
+    public static final OFGroup ZERO = OFGroup.of(ZERO_VAL);
+
+    public static final OFGroup NO_MASK = ANY;
+    public static final OFGroup FULL_MASK = ZERO;
+
+    /** raw openflow group number as a signed 32 bit integer */
+    private final int groupNumber;
+
+    /** private constructor. use of*-Factory methods instead */
+    private OFGroup(final int portNumber) {
+        this.groupNumber = portNumber;
+    }
+
+    /**
+     * get an OFGroup object corresponding to a raw 32-bit integer group number.
+     * NOTE: The group object may either be newly allocated or cached. Do not
+     * rely on either behavior.
+     *
+     * @param groupNumber the raw 32-bit group number
+     * @return a corresponding OFPort
+     */
+    public static OFGroup of(final int groupNumber) {
+        switch(groupNumber) {
+            case ZERO_VAL:
+                return MAX;
+            case MAX_VAL:
+                return MAX;
+            case ALL_VAL:
+                return ALL;
+            case ANY_VAL:
+                return ANY;
+            default:
+                if(UnsignedInts.compare(groupNumber, MAX_VAL) > 0) {
+                    // greater than max_val, but not one of the reserved values
+                    throw new IllegalArgumentException("Unknown special group number: "
+                            + groupNumber);
+                }
+                return new OFGroup(groupNumber);
+        }
+    }
+
+    /** return the group number as a int32 */
+    public int getGroupNumber() {
+        return groupNumber;
+    }
+
+    @Override
+    public String toString() {
+        return UnsignedInts.toString(groupNumber);
+    }
+
+    /** Extension of OFGroup for named groups */
+    static class NamedGroup extends OFGroup {
+        private final String name;
+
+        NamedGroup(final int portNo, final String name) {
+            super(portNo);
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof OFGroup))
+            return false;
+        OFGroup other = (OFGroup)obj;
+        if (other.groupNumber != this.groupNumber)
+            return false;
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 53;
+        int result = 1;
+        result = prime * result + groupNumber;
+        return result;
+    }
+
+    public void write4Bytes(ChannelBuffer c) {
+        c.writeInt(this.groupNumber);
+    }
+
+    public static OFGroup read4Bytes(ChannelBuffer c) throws OFParseError {
+        return OFGroup.of(c.readInt());
+    }
+
+    @Override
+    public OFGroup applyMask(OFGroup mask) {
+        return OFGroup.of(this.groupNumber & mask.groupNumber);
+    }
+
+    @Override
+    public int compareTo(OFGroup o) {
+        return UnsignedInts.compare(this.groupNumber, o.groupNumber);
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(groupNumber);
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java
index 0844d89..d1a23df 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java
@@ -2,6 +2,8 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
+
 public class OFMetadata implements OFValueType<OFMetadata> {
 
     static int LENGTH = 8;
@@ -67,4 +69,9 @@
     public int compareTo(OFMetadata o) {
         return u64.compareTo(o.u64);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        u64.putTo(sink);
+    }
 }
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..155a9db 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
@@ -4,6 +4,7 @@
 import org.projectfloodlight.openflow.annotations.Immutable;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 /**
@@ -87,12 +88,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 +166,8 @@
      */
     public static OFPort ofInt(final int portNumber) {
         switch (portNumber) {
+            case 0:
+                return PrecachedPort.p0;
             case 1:
                 return PrecachedPort.p1;
             case 2:
@@ -302,6 +310,8 @@
      */
     public static OFPort ofShort(final short portNumber) {
         switch (portNumber) {
+            case 0:
+                return PrecachedPort.p0;
             case 1:
                 return PrecachedPort.p1;
             case 2:
@@ -545,4 +555,9 @@
     public int compareTo(OFPort o) {
         return UnsignedInts.compare(this.portNumber, o.portNumber);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(portNumber);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java
new file mode 100644
index 0000000..49c8c4e
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java
@@ -0,0 +1,126 @@
+package org.projectfloodlight.openflow.types;
+
+
+/** User-facing object representing a bitmap of ports that can be matched on.
+ *  This is implemented by the custom BSN OXM type of_oxm_bsn_in_ports_182.
+ *
+ *  You can call set() on the builder for all the Ports you want to match on
+ *  and unset to exclude the port.
+ *
+ *  <b>Implementation note:</b> to comply with the matching semantics of OXM (which is a logical "AND" not "OR")
+ *  the underlying match uses a data format which is very unintuitive. The value is always
+ *  0, and the mask has the bits set for the ports that should <b>NOT</b> be included in the
+ *  range.
+ *
+ *  For the curious: We transformed the bitmap (a logical OR) problem into a logical
+ *  AND NOT problem.
+ *
+ *  We logically mean:   Inport is 1 OR 3
+ *  We technically say:  Inport IS NOT 2 AND IS NOT 4 AND IS NOT 5 AND IS NOT ....
+ *  The second term cannot be represented in OXM, the second can.
+ *
+ *  That said, all that craziness is hidden from the user of this object.
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class OFPortBitMap extends Masked<OFBitMask128> {
+
+    private OFPortBitMap(OFBitMask128 mask) {
+        super(OFBitMask128.NONE, mask);
+    }
+
+    /** @return whether or not the given port is logically included in the
+     *  match, i.e., whether a packet from in-port <emph>port</emph> be matched by
+     *  this OXM.
+     */
+    public boolean isOn(OFPort port) {
+        // see the implementation note above about the logical inversion of the mask
+        return !(this.mask.isOn(port.getPortNumber()));
+    }
+
+    public static OFPortBitMap 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 OFPortBitMap))
+            return false;
+        OFPortBitMap other = (OFPortBitMap)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() {
+
+        }
+
+        /** @return whether or not the given port is logically included in the
+         *  match, i.e., whether a packet from in-port <emph>port</emph> be matched by
+         *  this OXM.
+         */
+        public boolean isOn(OFPort port) {
+            // see the implementation note above about the logical inversion of the mask
+            return !(OFBitMask128.isBitOn(raw1, raw2, port.getPortNumber()));
+        }
+
+        /** remove this port from the match, i.e., packets from this in-port
+         *  will NOT be matched.
+         */
+        public Builder unset(OFPort port) {
+            // see the implementation note above about the logical inversion of the mask
+            int bit = port.getPortNumber();
+            if (bit < 0 || bit > 127)
+                throw new IndexOutOfBoundsException("Port number is out of bounds");
+            else if (bit == 127)
+                // the highest order bit in the bitmask is reserved. The switch will
+                // set that bit for all ports >= 127. The reason is that we don't want
+                // the OFPortMap to match all ports out of its range (i.e., a packet
+                // coming in on port 181 would match *any* OFPortMap).
+                throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
+            else if (bit < 64) {
+                raw2 |= ((long)1 << bit);
+            } else {
+                raw1 |= ((long)1 << (bit - 64));
+            }
+            return this;
+        }
+
+        /** add this port from the match, i.e., packets from this in-port
+         *  will NOT be matched.
+         */
+        public Builder set(OFPort port) {
+            // see the implementation note above about the logical inversion of the mask
+            int bit = port.getPortNumber();
+            if (bit < 0 || bit > 127)
+                throw new IndexOutOfBoundsException("Port number is out of bounds");
+            else if (bit == 127)
+                // the highest order bit in the bitmask is reserved. The switch will
+                // set that bit for all ports >= 127. The reason is that we don't want
+                // the OFPortMap to match all ports out of its range (i.e., a packet
+                // coming in on port 181 would match *any* OFPortMap).
+                throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
+            else if (bit < 64) {
+                raw2 &= ~((long)1 << bit);
+            } else {
+                raw1 &= ~((long)1 << (bit - 64));
+            }
+            return this;
+        }
+
+        public OFPortBitMap build() {
+            return new OFPortBitMap(OFBitMask128.of(raw1, raw2));
+        }
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java
index 3d8d1cd..03e84dd 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java
@@ -3,8 +3,9 @@
 
 
 
-public interface OFValueType<T extends OFValueType<T>> extends Comparable<T> {
+public interface OFValueType<T extends OFValueType<T>> extends Comparable<T>, PrimitiveSinkable {
     public int getLength();
 
     public T applyMask(T mask);
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/PrimitiveSinkable.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/PrimitiveSinkable.java
new file mode 100644
index 0000000..e50cb75
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/PrimitiveSinkable.java
@@ -0,0 +1,7 @@
+package org.projectfloodlight.openflow.types;
+
+import com.google.common.hash.PrimitiveSink;
+
+public interface PrimitiveSinkable {
+    public void putTo(PrimitiveSink sink);
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java
index ebb1966..950087d 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java
@@ -3,6 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Shorts;
 
 public class TableId implements OFValueType<TableId>, Comparable<TableId> {
@@ -14,7 +15,9 @@
     private static final short ALL_VAL = 0x00FF;
     private static final short NONE_VAL = 0x0000;
     public static final TableId NONE = new TableId(NONE_VAL);
+
     public static final TableId ALL = new TableId(ALL_VAL);
+    public static final TableId ZERO = NONE;
 
     private final short id;
 
@@ -89,4 +92,9 @@
         return Shorts.compare(this.id, other.id);
     }
 
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putByte((byte) id);
+    }
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java
index 540ad1a..01019b0 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java
@@ -3,6 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.Ints;
 
 /**
@@ -87,4 +88,9 @@
         return Ints.compare(port,  o.port);
     }
 
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putShort((short) port);
+    }
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java
index c52a74a..9de7e14 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java
@@ -22,6 +22,9 @@
 import org.projectfloodlight.openflow.protocol.OFMessageReader;
 import org.projectfloodlight.openflow.protocol.Writeable;
 
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.Ints;
+
 public class U16 implements Writeable, OFValueType<U16> {
     private final static short ZERO_VAL = 0;
     public final static U16 ZERO = new U16(ZERO_VAL);
@@ -113,6 +116,11 @@
 
     @Override
     public int compareTo(U16 o) {
-        return Integer.compare(f(raw), f(o.raw));
+        return Ints.compare(f(raw), f(o.raw));
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putShort(raw);
     }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
index daf5fa6..9fafc30 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
@@ -22,6 +22,7 @@
 import org.projectfloodlight.openflow.protocol.OFMessageReader;
 import org.projectfloodlight.openflow.protocol.Writeable;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 public class U32 implements Writeable, OFValueType<U32> {
@@ -117,4 +118,7 @@
         return UnsignedInts.compare(raw, o.raw);
     }
 
-}
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(raw);
+    }}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
index 8cd577f..d77d700 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
@@ -22,6 +22,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.protocol.Writeable;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedLongs;
 
 public class U64 implements Writeable, OFValueType<U64> {
@@ -120,4 +121,8 @@
         return UnsignedLongs.compare(raw, o.raw);
     }
 
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putLong(raw);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
index b85627e..078a846 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
@@ -22,6 +22,7 @@
 import org.projectfloodlight.openflow.protocol.OFMessageReader;
 import org.projectfloodlight.openflow.protocol.Writeable;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedBytes;
 
 public class U8 implements Writeable, OFValueType<U8> {
@@ -119,4 +120,8 @@
         return UnsignedBytes.compare(raw, o.raw);
     }
 
-}
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putByte(raw);
+    }
+ }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java
index 10e2ebc..b742da5 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java
@@ -4,6 +4,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedInts;
 
 @Immutable
@@ -11,6 +12,7 @@
     static final int LENGTH = 4;
     private final int rawValue;
 
+    public static final VRF ZERO = VRF.of(0x0);
     public static final VRF NO_MASK = VRF.of(0xFFFFFFFF);
     public static final VRF FULL_MASK = VRF.of(0x00000000);
 
@@ -75,4 +77,9 @@
     public int compareTo(VRF o) {
         return UnsignedInts.compare(rawValue, o.rawValue);
     }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putInt(rawValue);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java
index dcc7d60..cbb7004 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java
@@ -3,6 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 import com.google.common.primitives.UnsignedBytes;
 
 public class VlanPcp implements OFValueType<VlanPcp> {
@@ -74,5 +75,8 @@
     public int compareTo(VlanPcp o) {
         return UnsignedBytes.compare(pcp, o.pcp);
     }
-
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putByte(pcp);
+    }
 }
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..d370711 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
@@ -3,17 +3,48 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.projectfloodlight.openflow.exceptions.OFParseError;
 
+import com.google.common.hash.PrimitiveSink;
 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 +52,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 +109,11 @@
         return "0x" + Integer.toHexString(vid);
     }
 
-    public short getValue() {
+    public short getRawVid() {
         return vid;
     }
 
+
     @Override
     public int getLength() {
         return LENGTH;
@@ -79,18 +139,29 @@
         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
     public int compareTo(VlanVid o) {
         return Shorts.compare(vid, o.vid);
     }
-
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putShort(vid);
+    }
 }
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/main/java/org/projectfloodlight/openflow/util/ActionUtils.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ActionUtils.java
new file mode 100644
index 0000000..e0553a9
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ActionUtils.java
@@ -0,0 +1,43 @@
+package org.projectfloodlight.openflow.util;
+
+import java.util.List;
+
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFInstructionType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
+
+import com.google.common.collect.ImmutableList;
+
+public class ActionUtils {
+    private ActionUtils() {}
+
+    public static List<OFAction> getActions(OFFlowStatsEntry e) {
+        if(e.getVersion() == OFVersion.OF_10) {
+            return e.getActions();
+        } else {
+            for(OFInstruction i: e.getInstructions()) {
+                if(i.getType() == OFInstructionType.APPLY_ACTIONS) {
+                    return ((OFInstructionApplyActions) i).getActions();
+                }
+            }
+            return ImmutableList.of();
+        }
+    }
+
+    public static List<OFAction> getActions(OFFlowMod e) {
+        if(e.getVersion() == OFVersion.OF_10) {
+            return e.getActions();
+        } else {
+            for(OFInstruction i: e.getInstructions()) {
+                if(i.getType() == OFInstructionType.APPLY_ACTIONS) {
+                    return ((OFInstructionApplyActions) i).getActions();
+                }
+            }
+            return ImmutableList.of();
+        }
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java
index ea2c4a9..13cfdc7 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java
@@ -21,7 +21,12 @@
     public static String readFixedLengthString(ChannelBuffer bb, int length) {
         byte[] dst = new byte[length];
         bb.readBytes(dst, 0, length);
-        return new String(dst, Charsets.US_ASCII);
+        int validLength = 0;
+        for (validLength = 0; validLength < length; validLength++) {
+            if (dst[validLength] == 0)
+                break;
+        }
+        return new String(dst, 0, validLength, Charsets.US_ASCII);
     }
 
     public static void writeFixedLengthString(ChannelBuffer bb, String string,
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/FunnelUtils.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/FunnelUtils.java
new file mode 100644
index 0000000..f62d7f9
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/FunnelUtils.java
@@ -0,0 +1,14 @@
+package org.projectfloodlight.openflow.util;
+
+import java.util.List;
+
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+
+import com.google.common.hash.PrimitiveSink;
+
+public class FunnelUtils {
+    public static void putList(List<? extends PrimitiveSinkable> sinkables, PrimitiveSink sink) {
+        for(PrimitiveSinkable p: sinkables)
+            p.putTo(sink);
+    }
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
index dc25b12..3ccceb3 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
@@ -2,6 +2,8 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.util.Arrays;
@@ -29,9 +31,11 @@
             0x00ffffffffffffL
     };
 
-    String[] invalidMacs = {
+    String[] invalidMacStrings = {
             "",
             "1.2.3.4",
+            "0T:00:01:02:03:04",
+            "00:01:02:03:04:05:06",
             "00:ff:ef:12:12:ff:",
             "00:fff:ef:12:12:ff",
             "01:02:03:04:05;06",
@@ -39,6 +43,10 @@
             "01:02:03:04"
     };
 
+    byte[][] invalidMacBytes = {
+            new byte[]{0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
+            new byte[]{0x01, 0x01, 0x02, 0x03, 0x04}
+    };
 
     @Test
     public void testOfString() {
@@ -72,14 +80,64 @@
 
 
     @Test
-    public void testInvalidMacss() throws OFParseError {
-        for(String invalid : invalidMacs) {
+    public void testInvalidMacStrings() throws OFParseError {
+        for(String invalid : invalidMacStrings) {
             try {
                 MacAddress.of(invalid);
-                fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+                fail("Invalid MAC address "+invalid+ " should have raised IllegalArgumentException");
             } catch(IllegalArgumentException e) {
                 // ok
             }
         }
     }
+
+    @Test
+    public void testInvalidMacBytes() throws OFParseError {
+        for(byte[] invalid : invalidMacBytes) {
+            try {
+                MacAddress.of(invalid);
+                fail("Invalid MAC address bytes "+ Arrays.toString(invalid) + " should have raised IllegalArgumentException");
+            } catch(IllegalArgumentException e) {
+                // ok
+            }
+        }
+    }
+
+    //  Test data is imported from org.projectfloodlight.packet.EthernetTest
+    @Test
+    public void testToLong() {
+        assertEquals(
+                281474976710655L,
+                MacAddress.of(new byte[]{(byte) 0xff, (byte) 0xff,
+                        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}).getLong());
+
+        assertEquals(
+                1103823438081L,
+                MacAddress.of(new byte[] { (byte) 0x01, (byte) 0x01,
+                        (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01 }).getLong());
+
+        assertEquals(
+                141289400074368L,
+                MacAddress.of(new byte[] { (byte) 0x80, (byte) 0x80,
+                        (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80 }).getLong());
+
+    }
+
+    @Test
+    public void testIsBroadcast() {
+        assertTrue(MacAddress.of("FF:FF:FF:FF:FF:FF").isBroadcast());
+        assertTrue(MacAddress.of(-1).isBroadcast());
+        assertTrue(MacAddress.of(0x05FFFFFFFFFFFFL).isBroadcast());
+        assertFalse(MacAddress.of("11:22:33:44:55:66").isBroadcast());
+    }
+
+    @Test
+    public void testIsMulticast() {
+        assertTrue(MacAddress.of("01:80:C2:00:00:00").isMulticast());
+        assertFalse(MacAddress.of("00:80:C2:00:00:00").isMulticast());
+        assertFalse(MacAddress.of("FE:80:C2:00:00:00").isMulticast());
+        assertFalse(MacAddress.of(-1).isMulticast());
+        assertFalse(MacAddress.of(0x05FFFFFFFFFFFFL).isMulticast());
+        assertFalse(MacAddress.of("FF:FF:FF:FF:FF:FF").isMulticast());
+    }
 }
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
new file mode 100644
index 0000000..7f5ab5d
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.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 OFPortBitMapTest extends TestCase {
+
+    @Test
+    public void testOFPortBitMap() {
+        Boolean[] on = new Boolean[127];
+        for (int i = 0; i < 127; i++) {
+            on[i] = false;
+        }
+
+        OFPortBitMap.Builder builder = new OFPortBitMap.Builder();
+
+        for (int i = 0; i < 127; 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
+        OFPortBitMap portmap = builder.build();
+        //System.out.println(portmap);
+        Boolean[] actual = new Boolean[127];
+        for (int i = 0; i < 127; i++) {
+            actual[i] = false;
+        }
+        for (int i = 0; i < 127; i++) {
+            actual[i] = portmap.isOn(OFPort.of(i));
+        }
+        assertArrayEquals(on, actual);
+
+        // Turn some ports off
+        for (int i = 0; i < 127; i += 7) {
+            on[i] = false;
+            builder.unset(OFPort.of(i));
+        }
+
+        // Test again
+        portmap = builder.build();
+        actual = new Boolean[127];
+        for (int i = 0; i < 127; i++) {
+            actual[i] = false;
+        }
+        for (int i = 0; i < 127; i++) {
+            actual[i] = portmap.isOn(OFPort.of(i));
+        }
+        assertArrayEquals(on, actual);
+    }
+}
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
index 7fd0719..55e9a2d 100644
--- a/java_gen/templates/_imports.java
+++ b/java_gen/templates/_imports.java
@@ -1,5 +1,6 @@
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Set;
 import java.util.Map;
@@ -18,3 +19,5 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import com.google.common.hash.Funnel;
+import com.google.common.hash.PrimitiveSink;
diff --git a/java_gen/templates/const_serializer.java b/java_gen/templates/const_serializer.java
index 5710f9c..12ff28a 100644
--- a/java_gen/templates/const_serializer.java
+++ b/java_gen/templates/const_serializer.java
@@ -33,10 +33,7 @@
 
 package ${package};
 
-import org.projectfloodlight.openflow.types.*;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.projectfloodlight.openflow.exceptions.OFParseError;
-import org.projectfloodlight.openflow.protocol.OFVersion;
+//:: include('_imports.java')
 import ${enum.package}.${enum.name};
 
 public class ${class_name} {
@@ -60,6 +57,10 @@
         ${wire_type.write_op(version=version, name="toWireValue(e)")};
     }
 
+    public static void putTo(${enum.name} e, PrimitiveSink sink) {
+        ${wire_type.funnel_op(version=version, name="toWireValue(e)")};
+    }
+
     public static ${enum.name} ofWireValue(${int_wire_type} val) {
         switch(val) {
         //:: for entry, _ in entries:
@@ -71,6 +72,7 @@
         }
     }
 
+
     public static ${int_wire_type} toWireValue(${enum.name} e) {
         switch(e) {
         //:: for entry, _ in entries:
diff --git a/java_gen/templates/const_set_serializer.java b/java_gen/templates/const_set_serializer.java
index 4fcff22..4c624ee 100644
--- a/java_gen/templates/const_set_serializer.java
+++ b/java_gen/templates/const_set_serializer.java
@@ -33,14 +33,8 @@
 
 package ${package};
 
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Set;
+//:: include('_imports.java')
 
-import org.projectfloodlight.openflow.types.*;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.projectfloodlight.openflow.exceptions.OFParseError;
-import org.projectfloodlight.openflow.protocol.OFVersion;
 import ${enum.package}.${enum.name};
 
 public class ${class_name} {
@@ -64,6 +58,11 @@
         ${wire_type.write_op(version=version, name="toWireValue(set)")};
     }
 
+    public static void putTo(Set<${enum.name}> set, PrimitiveSink sink) {
+        ${wire_type.funnel_op(version=version, name="toWireValue(set)")};
+    }
+
+
     public static Set<${enum.name}> ofWireValue(${int_wire_type} val) {
         EnumSet<${enum.name}> set = EnumSet.noneOf(${enum.name}.class);
 
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
index 38cc127..239828e 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
@@ -25,6 +25,15 @@
                 case VLAN_PCP:
                     result = vlanPcp;
                     break;
+                case ARP_OP:
+                    result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+                    break;
+                case ARP_SPA:
+                    result = ipv4Src;
+                    break;
+                case ARP_TPA:
+                    result = ipv4Dst;
+                    break;
                 case IP_DSCP:
                     result = ipDscp;
                     break;
@@ -32,13 +41,13 @@
                     result = ipProto;
                     break;
                 case IPV4_SRC:
-                    result = ipv4Dst;
+                    result = ipv4Src;
                     break;
                 case IPV4_DST:
                     result = ipv4Dst;
                     break;
                 case TCP_SRC:
-                    result = ipv4Src;
+                    result = tcpSrc;
                     break;
                 case TCP_DST:
                     result = tcpDst;
@@ -77,10 +86,12 @@
             Object result;
             switch (field.id) {
                 case IPV4_SRC:
+                case ARP_SPA:
                     int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
                     result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
                     break;
                 case IPV4_DST:
+                case ARP_TPA:
                     int dstMaskedBits = Math.min(32, (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT);
                     int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
 
@@ -101,6 +112,9 @@
                 case ETH_TYPE:
                 case VLAN_VID:
                 case VLAN_PCP:
+                case ARP_OP:
+                case ARP_SPA:
+                case ARP_TPA:
                 case IP_DSCP:
                 case IP_PROTO:
                 case IPV4_SRC:
@@ -122,6 +136,8 @@
         @Override
         public boolean supportsMasked(MatchField<?> field) {
             switch (field.id) {
+                case ARP_SPA:
+                case ARP_TPA:
                 case IPV4_SRC:
                 case IPV4_DST:
                     return true;
@@ -145,6 +161,12 @@
                     return (this.wildcards & OFPFW_DL_VLAN) == 0;
                 case VLAN_PCP:
                     return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+                case ARP_OP:
+                    return (this.wildcards & OFPFW_NW_PROTO) == 0;
+                case ARP_SPA:
+                    return this.getIpv4SrcCidrMaskLen() >= 32;
+                case ARP_TPA:
+                    return this.getIpv4DstCidrMaskLen() >= 32;
                 case IP_DSCP:
                     return (this.wildcards & OFPFW_NW_TOS) == 0;
                 case IP_PROTO:
@@ -216,6 +238,12 @@
                     return (this.wildcards & OFPFW_DL_VLAN) != 0;
                 case VLAN_PCP:
                     return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+                case ARP_OP:
+                    return (this.wildcards & OFPFW_NW_PROTO) != 0;
+                case ARP_SPA:
+                    return this.getIpv4SrcCidrMaskLen() <= 0;
+                case ARP_TPA:
+                    return this.getIpv4DstCidrMaskLen() <= 0;
                 case IP_DSCP:
                     return (this.wildcards & OFPFW_NW_TOS) != 0;
                 case IP_PROTO:
@@ -248,11 +276,13 @@
         @Override
         public boolean isPartiallyMasked(MatchField<?> field) {
             switch (field.id) {
+                case ARP_SPA:
                 case IPV4_SRC:
                     int srcCidrLen = getIpv4SrcCidrMaskLen();
                     return srcCidrLen > 0 && srcCidrLen < 32;
+                case ARP_TPA:
                 case IPV4_DST:
-                    int dstCidrLen = getIpv4SrcCidrMaskLen();
+                    int dstCidrLen = getIpv4DstCidrMaskLen();
                     return dstCidrLen > 0 && dstCidrLen < 32;
                 default:
                     throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
@@ -300,10 +330,16 @@
                     setInPort((OFPort) value);
                     wildcards &= ~OFPFW_IN_PORT;
                     break;
+                case ARP_OP:
+                    setIpProto(IpProtocol.of((short)((ArpOpcode)value).getOpcode()));
+                    wildcards &= ~OFPFW_NW_PROTO;
+                    break;
+                case ARP_TPA:
                 case IPV4_DST:
                     setIpv4Dst((IPv4Address) value);
                     wildcards &= ~OFPFW_NW_DST_MASK;
                     break;
+                case ARP_SPA:
                 case IPV4_SRC:
                     setIpv4Src((IPv4Address) value);
                     wildcards &= ~OFPFW_NW_SRC_MASK;
@@ -347,6 +383,7 @@
                 case VLAN_VID:
                     setVlanVid((VlanVid) value);
                     wildcards &= ~OFPFW_DL_VLAN;
+                    break;
                 default:
                     throw new UnsupportedOperationException(
                             "OFMatch does not support matching on field " + field.getName());
@@ -359,6 +396,8 @@
                 F value, F mask) {
             initWildcards();
             switch (field.id) {
+                case ARP_SPA:
+                case ARP_TPA:
                 case IPV4_DST:
                 case IPV4_SRC:
                     Object valObj = value;
@@ -369,10 +408,12 @@
                         throw new UnsupportedOperationException("OFMatch only supports CIDR masks for IPv4");
                     int maskLen = 32 - Integer.bitCount(maskval);
                     switch(field.id) {
+                        case ARP_TPA:
                         case IPV4_DST:
                             setIpv4Dst(ip);
                             wildcards = (wildcards &~OFPFW_NW_DST_MASK) | (maskLen << OFPFW_NW_DST_SHIFT);
                             break;
+                        case ARP_SPA:
                         case IPV4_SRC:
                             setIpv4Src(ip);
                             wildcards = (wildcards &~OFPFW_NW_SRC_MASK) | (maskLen << OFPFW_NW_SRC_SHIFT);
@@ -428,10 +469,12 @@
                     setInPort(OFPort.of(0)); // NOTE: not 'NONE' -- that is 0xFF for ports
                     wildcards |= OFPFW_IN_PORT;
                     break;
+                case ARP_TPA:
                 case IPV4_DST:
                     setIpv4Dst(IPv4Address.NONE);
                     wildcards |= OFPFW_NW_DST_MASK;
                     break;
+                case ARP_SPA:
                 case IPV4_SRC:
                     setIpv4Src(IPv4Address.NONE);
                     wildcards |= OFPFW_NW_SRC_MASK;
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_clear_wildcards_stanza.java b/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_clear_wildcards_stanza.java
index 56b5662..9528ec0 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_clear_wildcards_stanza.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_clear_wildcards_stanza.java
@@ -3,7 +3,7 @@
             // ip_src, tcp_dst) to 0, AND ALSO SET THE WILDCARD to 0. It doesn't do that any more as of 1.1.2 and 1.4
             if(ethType.equals(EthType.IPv4)) {
                 // IP
-                if(ipProto.equals(IpProtocol.IP_PROTO_TCP) || ipProto.equals(IpProtocol.IP_PROTO_UDP) || ipProto.equals(IpProtocol.IP_PROTO_ICMP)) {
+                if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
                     // fully speced, wildcards and all values are fine
                     // normalize 32-63 ipv4 src 'mask' to a full bitmask
                     if((wildcards & OFPFW_NW_SRC_ALL) != 0)
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_set_wildcards_stanza.java b/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_set_wildcards_stanza.java
index 3545f55..09cb411 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_set_wildcards_stanza.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.Builder_normalize_set_wildcards_stanza.java
@@ -3,7 +3,7 @@
             // ip_src, tcp_dst) to 0, and sets the wildcard bit to 1.
             if(ethType.equals(EthType.IPv4)) {
                 // IP
-                if(ipProto.equals(IpProtocol.IP_PROTO_TCP) || ipProto.equals(IpProtocol.IP_PROTO_UDP) || ipProto.equals(IpProtocol.IP_PROTO_ICMP)) {
+                if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
                     // fully speced, wildcards and all values are fine
                     // normalize 32-63 ipv4 src 'mask' to a full bitmask
                     if((wildcards & OFPFW_NW_SRC_ALL) != 0)
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.java b/java_gen/templates/custom/OFMatchV1Ver10.java
index eaaacb0..82ff10f 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.java
@@ -61,6 +61,15 @@
             case VLAN_PCP:
                 result = vlanPcp;
                 break;
+            case ARP_OP:
+                result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+                break;
+            case ARP_SPA:
+                result = ipv4Src;
+                break;
+            case ARP_TPA:
+                result = ipv4Dst;
+                break;
             case IP_DSCP:
                 result = ipDscp;
                 break;
@@ -68,7 +77,7 @@
                 result = ipProto;
                 break;
             case IPV4_SRC:
-                result = ipv4Dst;
+                result = ipv4Src;
                 break;
             case IPV4_DST:
                 result = ipv4Dst;
@@ -114,10 +123,12 @@
             return null;
         Object result;
         switch (field.id) {
+            case ARP_SPA:
             case IPV4_SRC:
                 int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
                 result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
                 break;
+            case ARP_TPA:
             case IPV4_DST:
                 int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
 
@@ -138,6 +149,9 @@
             case ETH_TYPE:
             case VLAN_VID:
             case VLAN_PCP:
+            case ARP_OP:
+            case ARP_SPA:
+            case ARP_TPA:
             case IP_DSCP:
             case IP_PROTO:
             case IPV4_SRC:
@@ -159,6 +173,8 @@
     @Override
     public boolean supportsMasked(MatchField<?> field) {
         switch (field.id) {
+            case ARP_SPA:
+            case ARP_TPA:
             case IPV4_SRC:
             case IPV4_DST:
                 return true;
@@ -185,6 +201,12 @@
                 return (this.wildcards & OFPFW_DL_VLAN) == 0;
             case VLAN_PCP:
                 return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+            case ARP_OP:
+                return (this.wildcards & OFPFW_NW_PROTO) == 0;
+            case ARP_SPA:
+                return this.getIpv4SrcCidrMaskLen() >= 32;
+            case ARP_TPA:
+                return this.getIpv4DstCidrMaskLen() >= 32;
             case IP_DSCP:
                 return (this.wildcards & OFPFW_NW_TOS) == 0;
             case IP_PROTO:
@@ -259,6 +281,12 @@
                 return (this.wildcards & OFPFW_DL_VLAN) != 0;
             case VLAN_PCP:
                 return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+            case ARP_OP:
+                return (this.wildcards & OFPFW_NW_PROTO) != 0;
+            case ARP_SPA:
+                return this.getIpv4SrcCidrMaskLen() <= 0;
+            case ARP_TPA:
+                return this.getIpv4DstCidrMaskLen() <= 0;
             case IP_DSCP:
                 return (this.wildcards & OFPFW_NW_TOS) != 0;
             case IP_PROTO:
@@ -294,9 +322,11 @@
             return false;
 
         switch (field.id) {
+            case ARP_SPA:
             case IPV4_SRC:
                 int srcCidrLen = getIpv4SrcCidrMaskLen();
                 return srcCidrLen > 0 && srcCidrLen < 32;
+            case ARP_TPA:
             case IPV4_DST:
                 int dstCidrLen = getIpv4SrcCidrMaskLen();
                 return dstCidrLen > 0 && dstCidrLen < 32;
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index aa68d04..7b3b762 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,33 +202,41 @@
 //:: 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:
-            // align message to ${msg.align} bytes
+            //:: if msg.length_includes_align:
+            // align message to ${msg.align} bytes (length contains aligned value)
+            bb.skipBytes(length - (bb.readerIndex() - start));
+            //:: else:
+            // align message to ${msg.align} bytes (length does not contain alignment)
             bb.skipBytes(((length + ${msg.align-1})/${msg.align} * ${msg.align} ) - length );
             //:: #endif
+            //:: #endif
 
             //:: if msg.data_members:
             //:: if os.path.exists("%s/custom/%s.Reader_normalize_stanza.java" % (template_dir, msg.name)):
@@ -237,6 +252,33 @@
         }
     }
 
+    public void putTo(PrimitiveSink sink) {
+        FUNNEL.funnel(this, sink);
+    }
+
+    final static ${impl_class}Funnel FUNNEL = new ${impl_class}Funnel();
+    static class ${impl_class}Funnel implements Funnel<${impl_class}> {
+        private static final long serialVersionUID = 1L;
+        @Override
+        public void funnel(${impl_class} message, PrimitiveSink sink) {
+//:: for prop in msg.members:
+//:: if prop.is_virtual:
+//::    continue
+//:: elif prop.is_data:
+            ${prop.java_type.funnel_op(version, "message." + prop.name, pub_type=True)};
+//:: elif prop.is_pad:
+            // skip pad (${prop.length} bytes)
+//:: elif prop.is_fixed_value:
+            // fixed value property ${prop.name} = ${prop.value}
+            ${prop.java_type.funnel_op(version, prop.priv_value, pub_type=False)};
+//:: else:
+            // FIXME: skip funnel of ${prop.name}
+//:: #endif
+//:: #endfor
+        }
+    }
+
+
     public void writeTo(ChannelBuffer bb) {
         WRITER.write(bb, this);
     }
@@ -290,10 +332,13 @@
 //:: if not msg.is_fixed_length:
             // update length field
             int length = bb.writerIndex() - startIndex;
-            bb.setShort(lengthIndex, length);
+            //:: if msg.align:
+            int alignedLength = ((length + ${msg.align-1})/${msg.align} * ${msg.align});
+            //:: #endif
+            bb.setShort(lengthIndex, ${"alignedLength" if msg.length_includes_align else "length"});
             //:: if msg.align:
             // align message to ${msg.align} bytes
-            bb.writeZero( ((length + ${msg.align-1})/${msg.align} * ${msg.align}) - length);
+            bb.writeZero(alignedLength - length);
             //:: #endif
 //:: #end
 
@@ -354,6 +399,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_factories.java b/java_gen/templates/of_factories.java
index 0044335..f8c9a80 100644
--- a/java_gen/templates/of_factories.java
+++ b/java_gen/templates/of_factories.java
@@ -36,6 +36,9 @@
 //:: include("_imports.java")
 
 public final class OFFactories {
+
+    private static final GenericReader GENERIC_READER = new GenericReader();
+
     public static OFFactory getFactory(OFVersion version) {
         switch(version) {
             //:: for v in versions:
@@ -46,4 +49,25 @@
                 throw new IllegalArgumentException("Unknown version: "+version);
             }
     }
+    
+    private static class GenericReader implements OFMessageReader<OFMessage> {
+        public OFMessage readFrom(ChannelBuffer bb) throws OFParseError {
+            short wireVersion = U8.f(bb.getByte(0));
+            OFFactory factory;
+            switch (wireVersion) {
+            //:: for v in versions:
+            case ${v.int_version}:
+                factory = org.projectfloodlight.openflow.protocol.ver${v.of_version}.OFFactoryVer${v.of_version}.INSTANCE;
+                break;
+            //:: #endfor
+            default:
+                throw new IllegalArgumentException("Unknown wire version: " + wireVersion);
+            }
+            return factory.getReader().readFrom(bb);
+        }
+    }
+
+    public static OFMessageReader<OFMessage> getGenericReader() {
+        return GENERIC_READER;
+    }
 }
diff --git a/java_gen/templates/of_factory_class.java b/java_gen/templates/of_factory_class.java
index 5263226..eef1e04 100644
--- a/java_gen/templates/of_factory_class.java
+++ b/java_gen/templates/of_factory_class.java
@@ -72,6 +72,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:
@@ -164,4 +170,7 @@
     }
 //:: #endif
 
+    public OFVersion getVersion() {
+            return OFVersion.${factory.version.constant_version};
+    }
 }
diff --git a/java_gen/templates/of_factory_interface.java b/java_gen/templates/of_factory_interface.java
index 48ea34a..9a77aa7 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
 
     OFMessageReader<${factory.base_class}> getReader();
-
+    OFVersion getVersion();
 //:: 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..cd85a74 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();
 
@@ -76,6 +80,7 @@
 
         // FIXME should invoke the overall reader once implemented
         ${var_type} ${var_name}Read = ${msg.name}.READER.readFrom(input);
+        assertEquals(${msg.constant_name}_SERIALIZED.length, input.readerIndex());
 
         assertEquals(${var_name}Built, ${var_name}Read);
    }
@@ -89,6 +94,7 @@
 
        // FIXME should invoke the overall reader once implemented
        ${var_type} ${var_name} = ${msg.name}.READER.readFrom(input);
+       assertEquals(${msg.constant_name}_SERIALIZED.length, input.readerIndex());
 
        // write message again
        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
diff --git a/lang_wireshark.py b/lang_wireshark.py
new file mode 100644
index 0000000..9f73543
--- /dev/null
+++ b/lang_wireshark.py
@@ -0,0 +1,43 @@
+# 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.
+
+"""
+Wireshark dissector backend for LOXI
+
+Target directory structure:
+    wireshark:
+        openflow.lua
+
+The user will copy openflow.lua into ~/.wireshark/plugins, where it will be
+loaded automatically by Wireshark.
+"""
+
+import wireshark_gen
+
+targets = {
+    'wireshark/openflow.lua' : wireshark_gen.generate
+}
diff --git a/loxi_front_end/match.py b/loxi_front_end/match.py
index 20d5030..c715455 100644
--- a/loxi_front_end/match.py
+++ b/loxi_front_end/match.py
@@ -145,24 +145,7 @@
         takes_mask_in_spec=False,
         order=211,
         ),
-    ipv4_src = dict(
-        name="ipv4_src",
-        m_type="of_ipv4_t",
-        v1_wc_shift=8,
-        print_type="PRIx32",
-        conditions="is_ipv4(match)",
-        takes_mask_in_spec=True,
-        order=300,
-        ),
-    ipv4_dst = dict(
-        name="ipv4_dst",
-        m_type="of_ipv4_t",
-        v1_wc_shift=14,
-        print_type="PRIx32",
-        conditions="is_ipv4(match)",
-        takes_mask_in_spec=True,
-        order=301,
-        ),
+
     ip_dscp = dict(
         name="ip_dscp",
         m_type="uint8_t",
@@ -191,6 +174,24 @@
         takes_mask_in_spec=False,
         order=320,
         ),
+    ipv4_src = dict(
+        name="ipv4_src",
+        m_type="of_ipv4_t",
+        v1_wc_shift=8,
+        print_type="PRIx32",
+        conditions="is_ipv4(match)",
+        takes_mask_in_spec=True,
+        order=330,
+        ),
+    ipv4_dst = dict(
+        name="ipv4_dst",
+        m_type="of_ipv4_t",
+        v1_wc_shift=14,
+        print_type="PRIx32",
+        conditions="is_ipv4(match)",
+        takes_mask_in_spec=True,
+        order=331,
+        ),
 
     tcp_dst = dict(
         name="tcp_dst",
@@ -270,7 +271,7 @@
         print_type="PRIx16",
         conditions="is_arp(match)",
         takes_mask_in_spec=False,
-        order=250,
+        order=450,
         ),
 
     arp_spa = dict(
@@ -279,7 +280,7 @@
         print_type="PRIx32",
         conditions="is_arp(match)",
         takes_mask_in_spec=True,
-        order=251,
+        order=451,
         ),
     arp_tpa = dict(
         name="arp_tpa",
@@ -287,7 +288,7 @@
         print_type="PRIx32",
         conditions="is_arp(match)",
         takes_mask_in_spec=True,
-        order=252,
+        order=452,
         ),
 
     arp_sha = dict(
@@ -296,7 +297,7 @@
         print_type="\"p\"",
         conditions="is_arp(match)",
         takes_mask_in_spec=False,
-        order=253,
+        order=453,
         ),
     arp_tha = dict(
         name="arp_tha",
@@ -304,7 +305,7 @@
         print_type="\"p\"",
         conditions="is_arp(match)",
         takes_mask_in_spec=False,
-        order=254,
+        order=454,
         ),
 
     ipv6_src = dict(
@@ -313,7 +314,7 @@
         print_type="\"p\"",
         conditions="is_ipv6(match)",
         takes_mask_in_spec=True,
-        order=350,
+        order=500,
         ),
     ipv6_dst = dict(
         name="ipv6_dst",
@@ -321,7 +322,7 @@
         print_type="\"p\"",
         conditions="is_ipv6(match)",
         takes_mask_in_spec=True,
-        order=351,
+        order=501,
         ),
 
     ipv6_flabel = dict(
@@ -330,7 +331,7 @@
         print_type="PRIx32",
         conditions="is_ipv6(match)",
         takes_mask_in_spec=False, # Comment in openflow.h says True
-        order=360,
+        order=502,
         ),
 
     icmpv6_type = dict(
@@ -339,7 +340,7 @@
         print_type="PRIx8",
         conditions="is_icmp_v6(match)",
         takes_mask_in_spec=False,
-        order=440,
+        order=510,
         ),
     icmpv6_code = dict(
         name="icmpv6_code",
@@ -347,7 +348,7 @@
         print_type="PRIx8",
         conditions="is_icmp_v6(match)",
         takes_mask_in_spec=False,
-        order=441,
+        order=511,
         ),
 
     ipv6_nd_target = dict(
@@ -356,7 +357,7 @@
         print_type="\"p\"",
         conditions="", # fixme
         takes_mask_in_spec=False,
-        order=442,
+        order=512,
         ),
 
     ipv6_nd_sll = dict(
@@ -365,7 +366,7 @@
         print_type="\"p\"",
         conditions="", # fixme
         takes_mask_in_spec=False,
-        order=443,
+        order=520,
         ),
     ipv6_nd_tll = dict(
         name="ipv6_nd_tll",
@@ -373,7 +374,7 @@
         print_type="\"p\"",
         conditions="", # fixme
         takes_mask_in_spec=False,
-        order=444,
+        order=521,
         ),
 
     mpls_label = dict(
@@ -383,7 +384,7 @@
         print_type="PRIx32",
         conditions="",
         takes_mask_in_spec=False,
-        order=500,
+        order=600,
         ),
     mpls_tc = dict(
         name="mpls_tc",
@@ -392,7 +393,71 @@
         print_type="PRIx8",
         conditions="",
         takes_mask_in_spec=False,
-        order=501,
+        order=601,
+        ),
+
+    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,
+        ),
+
+    bsn_lag_id = dict(
+        name="bsn_lag_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=1001,
+        ),
+
+    bsn_vrf = dict(
+        name="bsn_vrf",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=1002,
+        ),
+
+    bsn_global_vrf_allowed = dict(
+        name="bsn_global_vrf_allowed",
+        m_type="uint8_t",
+        print_type="PRIu8",
+        conditions="",
+        takes_mask_in_spec=False,
+        order=1003,
+        ),
+
+    bsn_l3_interface_class_id = dict(
+        name="bsn_l3_interface_class_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=1003,
+        ),
+
+    bsn_l3_src_class_id = dict(
+        name="bsn_l3_src_class_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=1004,
+        ),
+
+    bsn_l3_dst_class_id = dict(
+        name="bsn_l3_dst_class_id",
+        m_type="uint32_t",
+        print_type="PRIu32",
+        conditions="",
+        takes_mask_in_spec=True,
+        order=1005,
         ),
 )
 
diff --git a/loxi_front_end/parser.py b/loxi_front_end/parser.py
index f2cf4b0..4a465f7 100644
--- a/loxi_front_end/parser.py
+++ b/loxi_front_end/parser.py
@@ -56,7 +56,7 @@
 type_member = P.Group(tag('type') + any_type + identifier + s('==') + integer)
 data_member = P.Group(tag('data') + any_type - identifier)
 
-struct_param_name = kw("align")
+struct_param_name = kw("align") | kw("length_includes_align")
 struct_param = P.Group(struct_param_name - s('=') - word)
 struct_param_list = P.Forward()
 struct_param_list << struct_param + P.Optional(s(',') - P.Optional(struct_param_list))
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/loxi_ir.py b/loxi_ir.py
index ae89207..a70f041 100644
--- a/loxi_ir.py
+++ b/loxi_ir.py
@@ -62,7 +62,12 @@
 @param classes List of OFClass objects
 @param enums List of Enum objects
 """
-OFProtocol = namedtuple('OFProtocol', ['wire_version', 'classes', 'enums'])
+class OFProtocol(namedtuple('OFProtocol', ['wire_version', 'classes', 'enums'])):
+    def class_by_name(self, name):
+        return find(lambda ofclass: ofclass.name == name, self.classes)
+
+    def enum_by_name(self, name):
+        return find(lambda enum: enum.name == name, self.enums)
 
 """
 An OpenFlow class
@@ -79,7 +84,11 @@
 """
 class OFClass(namedtuple('OFClass', ['name', 'superclass', 'members', 'virtual', 'params'])):
     def member_by_name(self, name):
-        return find(self.members, lambda m: hasattr(m, "name") and m.name == name)
+        return find(lambda m: hasattr(m, "name") and m.name == name, self.members)
+
+    @property
+    def discriminator(self):
+        return find(lambda m: type(m) == OFDiscriminatorMember, self.members)
 
 """
 Normal field
diff --git a/loxigen.py b/loxigen.py
index f756dc0..05dd6b5 100755
--- a/loxigen.py
+++ b/loxigen.py
@@ -499,7 +499,13 @@
             if not (parent and subcls):
                 continue
             if parent == 'of_oxm':
-                val = (find_type_value(ofclass, 'type_len') >> 8) & 0xff
+                type_len = find_type_value(ofclass, 'type_len')
+                oxm_class = (type_len >> 16) & 0xffff
+                if oxm_class != 0x8000:
+                    # Do not include experimenter OXMs in the main table
+                    val = type_maps.invalid_type
+                else:
+                    val = (type_len >> 8) & 0xff
             else:
                 val = find_type_value(ofclass, 'type')
             type_maps.inheritance_data[parent][wire_version][subcls] = val
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_flow_idle b/openflow_input/bsn_flow_idle
new file mode 100644
index 0000000..40a95d8
--- /dev/null
+++ b/openflow_input/bsn_flow_idle
@@ -0,0 +1,99 @@
+// 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 4
+
+/*
+ * Notification of idle flows
+ *
+ * This extension allows the controller to request to be notified periodically
+ * about idle flows. It is very similar to the flow_removed message in standard
+ * OpenFlow, but does not delete the idle flows.
+ *
+ * If the extension is enabled using of_bsn_flow_idle_enable_set_request and
+ * the OFPFF_BSN_SEND_IDLE bit is set in the flow-mod, then the idle_timeout
+ * field in the flow-mod is not used for standard flow expiration. Instead,
+ * the switch will send an of_bsn_flow_idle message every idle_timeout seconds
+ * if the flow was not used during that period.
+ */
+
+struct of_bsn_flow_idle_enable_set_request : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 36;
+    uint32_t enable;        // 0 to disable the extension, 1 to enable it
+};
+
+struct of_bsn_flow_idle_enable_set_reply : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 37;
+    uint32_t enable;        // Resulting state, 0 disabled, 1 enabled
+    uint32_t status;        // Result code: 0 success
+};
+
+struct of_bsn_flow_idle_enable_get_request : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 38;
+};
+
+struct of_bsn_flow_idle_enable_get_reply : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 39;
+    uint32_t enabled;       // 0 if feature is disabled; 1 if feature enabled
+};
+
+struct of_bsn_flow_idle : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 40;
+    uint64_t cookie;
+    uint16_t priority;
+    uint8_t table_id;
+    pad(5); // align to 8 bytes
+    of_match_t match;
+};
diff --git a/openflow_input/bsn_global_vrf_allowed b/openflow_input/bsn_global_vrf_allowed
new file mode 100644
index 0000000..543c6fd
--- /dev/null
+++ b/openflow_input/bsn_global_vrf_allowed
@@ -0,0 +1,47 @@
+// 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
+
+/*
+ * Global VRF allowed flag for SwitchLight
+ */
+
+struct of_oxm_bsn_global_vrf_allowed : of_oxm {
+    uint32_t type_len == 0x00030601;
+    uint8_t value;
+};
+
+struct of_oxm_bsn_global_vrf_allowed_masked : of_oxm {
+    uint32_t type_len == 0x00030701;
+    uint8_t value;
+    uint8_t value_mask;
+};
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_l3_dst_class_id b/openflow_input/bsn_l3_dst_class_id
new file mode 100644
index 0000000..385add7
--- /dev/null
+++ b/openflow_input/bsn_l3_dst_class_id
@@ -0,0 +1,47 @@
+// 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
+
+/*
+ * L3 destination class ID for SwitchLight
+ */
+
+struct of_oxm_bsn_l3_dst_class_id : of_oxm {
+    uint32_t type_len == 0x00030c04;
+    uint32_t value;
+};
+
+struct of_oxm_bsn_l3_dst_class_id_masked : of_oxm {
+    uint32_t type_len == 0x00030d04;
+    uint32_t value;
+    uint32_t value_mask;
+};
diff --git a/openflow_input/bsn_l3_interface_class_id b/openflow_input/bsn_l3_interface_class_id
new file mode 100644
index 0000000..efeb949
--- /dev/null
+++ b/openflow_input/bsn_l3_interface_class_id
@@ -0,0 +1,47 @@
+// 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
+
+/*
+ * L3 interface class ID for SwitchLight
+ */
+
+struct of_oxm_bsn_l3_interface_class_id : of_oxm {
+    uint32_t type_len == 0x00030804;
+    uint32_t value;
+};
+
+struct of_oxm_bsn_l3_interface_class_id_masked : of_oxm {
+    uint32_t type_len == 0x00030904;
+    uint32_t value;
+    uint32_t value_mask;
+};
diff --git a/openflow_input/bsn_l3_src_class_id b/openflow_input/bsn_l3_src_class_id
new file mode 100644
index 0000000..f18aab9
--- /dev/null
+++ b/openflow_input/bsn_l3_src_class_id
@@ -0,0 +1,47 @@
+// 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
+
+/*
+ * L3 source class ID for SwitchLight
+ */
+
+struct of_oxm_bsn_l3_src_class_id : of_oxm {
+    uint32_t type_len == 0x00030a04;
+    uint32_t value;
+};
+
+struct of_oxm_bsn_l3_src_class_id_masked : of_oxm {
+    uint32_t type_len == 0x00030b04;
+    uint32_t value;
+    uint32_t value_mask;
+};
diff --git a/openflow_input/bsn_lag_id b/openflow_input/bsn_lag_id
new file mode 100644
index 0000000..c96c1d6
--- /dev/null
+++ b/openflow_input/bsn_lag_id
@@ -0,0 +1,47 @@
+// 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
+
+/*
+ * Ingress LAG ID for SwitchLight
+ */
+
+struct of_oxm_bsn_lag_id : of_oxm {
+    uint32_t type_len == 0x00030204;
+    uint32_t value;
+};
+
+struct of_oxm_bsn_lag_id_masked : of_oxm {
+    uint32_t type_len == 0x00030304;
+    uint32_t value;
+    uint32_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/bsn_vrf b/openflow_input/bsn_vrf
new file mode 100644
index 0000000..3641faa
--- /dev/null
+++ b/openflow_input/bsn_vrf
@@ -0,0 +1,47 @@
+// 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
+
+/*
+ * Virtual Routing/Forwarding ID for SwitchLight
+ */
+
+struct of_oxm_bsn_vrf : of_oxm {
+    uint32_t type_len == 0x00030404;
+    uint32_t value;
+};
+
+struct of_oxm_bsn_vrf_masked : of_oxm {
+    uint32_t type_len == 0x00030504;
+    uint32_t value;
+    uint32_t value_mask;
+};
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 1a23ce4..ad2e76f 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -35,8 +35,8 @@
     OFP_MAX_TABLE_NAME_LEN = 32,
     OFP_MAX_PORT_NAME_LEN = 16,
 
-    OFP_TCP_PORT = 6633,
-    OFP_SSL_PORT = 6633,
+    OFP_TCP_PORT = 6653,
+    OFP_SSL_PORT = 6653,
 
     OFP_ETH_ALEN = 6,
 
@@ -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,
@@ -94,6 +94,7 @@
     OFPPC_NO_FLOOD = 0x10,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
+    OFPPC_BSN_MIRROR_DEST = 0x80000000,
 };
 
 enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
@@ -175,7 +176,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) {
@@ -210,18 +211,22 @@
     OFPFF_EMERG = 0x4,
 };
 
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+};
+
+
 enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     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 +264,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 +275,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 +412,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 +703,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;
 };
 
@@ -766,7 +829,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
 };
 
 struct of_stats_reply : of_header {
@@ -775,7 +838,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
 };
 
 struct of_desc_stats_request : of_stats_request {
@@ -784,7 +847,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
 };
 
 struct of_desc_stats_reply : of_stats_reply {
@@ -793,7 +856,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     of_desc_str_t mfr_desc;
     of_desc_str_t hw_desc;
     of_desc_str_t sw_desc;
@@ -807,7 +870,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     of_match_t match;
     uint8_t table_id;
     pad(1);
@@ -820,7 +883,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     list(of_flow_stats_entry_t) entries;
 };
 
@@ -830,7 +893,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     of_match_t match;
     uint8_t table_id;
     pad(1);
@@ -843,7 +906,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     uint64_t packet_count;
     uint64_t byte_count;
     uint32_t flow_count;
@@ -856,7 +919,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
 };
 
 struct of_table_stats_reply : of_stats_reply {
@@ -865,7 +928,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     list(of_table_stats_entry_t) entries;
 };
 
@@ -875,7 +938,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     of_port_no_t port_no;
     pad(6);
 };
@@ -886,7 +949,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     list(of_port_stats_entry_t) entries;
 };
 
@@ -896,7 +959,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     of_port_no_t port_no;
     pad(2);
     uint32_t queue_id;
@@ -908,7 +971,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     list(of_queue_stats_entry_t) entries;
 };
 
@@ -918,7 +981,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0xffff;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     uint32_t experimenter == ?;
     of_octets_t data;
 };
@@ -929,7 +992,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0xffff;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     uint32_t experimenter == ?;
     of_octets_t data;
 };
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index 937ac52..9b72e8c 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -35,8 +35,8 @@
     OFP_MAX_TABLE_NAME_LEN = 32,
     OFP_MAX_PORT_NAME_LEN = 16,
 
-    OFP_TCP_PORT = 6633,
-    OFP_SSL_PORT = 6633,
+    OFP_TCP_PORT = 6653,
+    OFP_SSL_PORT = 6653,
 
     OFP_ETH_ALEN = 6,
 
@@ -72,9 +72,6 @@
     OFPP_ALL = 0xfffffffc,
     OFPP_CONTROLLER = 0xfffffffd,
     OFPP_LOCAL = 0xfffffffe,
-};
-
-enum ofp_port_no(wire_type=uint32_t, complete=False) {
     OFPP_ANY = 0xffffffff,
 };
 
@@ -135,6 +132,7 @@
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
+    OFPPC_BSN_MIRROR_DEST = 0x80000000,
 };
 
 enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
@@ -386,7 +384,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,
@@ -398,6 +396,11 @@
     OFPST_EXPERIMENTER = 0xffff,
 };
 
+// none defined
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+};
+
+
 enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
@@ -529,7 +532,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 +1014,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;
 };
 
@@ -1094,7 +1205,7 @@
 
 struct of_group_desc_stats_entry {
     uint16_t length;
-    uint8_t type;
+    uint8_t group_type;
     pad(1);
     uint32_t group_id;
     list(of_bucket_t) buckets;
@@ -1108,7 +1219,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1118,7 +1229,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
 };
 
@@ -1128,7 +1239,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1138,7 +1249,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     of_desc_str_t mfr_desc;
     of_desc_str_t hw_desc;
@@ -1153,7 +1264,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint8_t table_id;
     pad(3);
@@ -1171,7 +1282,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_flow_stats_entry_t) entries;
 };
@@ -1182,7 +1293,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint8_t table_id;
     pad(3);
@@ -1200,7 +1311,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     uint64_t packet_count;
     uint64_t byte_count;
@@ -1214,7 +1325,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1224,7 +1335,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_table_stats_entry_t) entries;
 };
@@ -1235,7 +1346,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     of_port_no_t port_no;
     pad(4);
@@ -1247,7 +1358,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_port_stats_entry_t) entries;
 };
@@ -1258,7 +1369,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     of_port_no_t port_no;
     uint32_t queue_id;
@@ -1270,7 +1381,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_queue_stats_entry_t) entries;
 };
@@ -1281,7 +1392,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 6;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint32_t group_id;
     pad(4);
@@ -1293,7 +1404,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 6;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_group_stats_entry_t) entries;
 };
@@ -1304,7 +1415,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 7;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1314,7 +1425,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 7;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_group_desc_stats_entry_t) entries;
 };
@@ -1325,7 +1436,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0xffff;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint32_t experimenter == ?;
     pad(4);
@@ -1338,7 +1449,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0xffff;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     uint32_t experimenter == ?;
     pad(4);
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index e8f95ee..e9d915a 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -35,8 +35,8 @@
     OFP_MAX_TABLE_NAME_LEN = 32,
     OFP_MAX_PORT_NAME_LEN = 16,
 
-    OFP_TCP_PORT = 6633,
-    OFP_SSL_PORT = 6633,
+    OFP_TCP_PORT = 6653,
+    OFP_SSL_PORT = 6653,
 
     OFP_ETH_ALEN = 6,
 
@@ -68,9 +68,6 @@
     OFPP_ALL = 0xfffffffc,
     OFPP_CONTROLLER = 0xfffffffd,
     OFPP_LOCAL = 0xfffffffe,
-};
-
-enum ofp_port_no(wire_type=uint32_t, complete=False) {
     OFPP_ANY = 0xffffffff,
 };
 
@@ -138,6 +135,7 @@
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
+    OFPPC_BSN_MIRROR_DEST = 0x80000000,
 };
 
 enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
@@ -292,7 +290,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 +305,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 +327,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 +408,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,
@@ -423,6 +421,9 @@
     OFPST_EXPERIMENTER = 0xffff,
 };
 
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+};
+
 enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
@@ -569,7 +570,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;
 };
@@ -599,7 +600,7 @@
     pad(4);
 };
 
-struct of_match_v3(align=8) {
+struct of_match_v3(align=8, length_includes_align=False) {
     uint16_t type == 1;
     uint16_t length;
     list(of_oxm_t) oxm_list;
@@ -690,13 +691,13 @@
     pad(4);
 };
 
-struct of_action_set_field : of_action {
+struct of_action_set_field(align=8, length_includes_align=True) : of_action {
     uint16_t type == 25;
     uint16_t len;
     of_oxm_t field;
 };
 
-struct of_action_experimenter : of_action {
+struct of_action_experimenter(align=8, length_includes_align=True) : of_action {
     uint16_t type == 65535;
     uint16_t len;
     uint32_t experimenter == ?;
@@ -954,21 +955,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
@@ -1053,7 +1172,7 @@
 
 struct of_group_desc_stats_entry {
     uint16_t length;
-    uint8_t type;
+    uint8_t group_type;
     pad(1);
     uint32_t group_id;
     list(of_bucket_t) buckets;
@@ -1068,7 +1187,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1078,7 +1197,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
 };
 
@@ -1088,7 +1207,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1098,7 +1217,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     of_desc_str_t mfr_desc;
     of_desc_str_t hw_desc;
@@ -1113,7 +1232,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint8_t table_id;
     pad(3);
@@ -1131,7 +1250,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_flow_stats_entry_t) entries;
 };
@@ -1142,7 +1261,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint8_t table_id;
     pad(3);
@@ -1160,7 +1279,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     uint64_t packet_count;
     uint64_t byte_count;
@@ -1174,7 +1293,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1184,7 +1303,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_table_stats_entry_t) entries;
 };
@@ -1195,7 +1314,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     of_port_no_t port_no;
     pad(4);
@@ -1207,7 +1326,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_port_stats_entry_t) entries;
 };
@@ -1218,7 +1337,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     of_port_no_t port_no;
     uint32_t queue_id;
@@ -1230,7 +1349,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_queue_stats_entry_t) entries;
 };
@@ -1241,7 +1360,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 6;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint32_t group_id;
     pad(4);
@@ -1253,7 +1372,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 6;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_group_stats_entry_t) entries;
 };
@@ -1264,7 +1383,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 7;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1274,7 +1393,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 7;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_group_desc_stats_entry_t) entries;
 };
@@ -1285,7 +1404,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 8;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1295,7 +1414,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 8;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     uint32_t types;
     uint32_t capabilities;
@@ -1315,7 +1434,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0xffff;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint32_t experimenter == ?;
     uint32_t subtype;
@@ -1328,7 +1447,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0xffff;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     uint32_t experimenter == ?;
     uint32_t subtype;
@@ -1400,7 +1519,7 @@
     uint8_t type == 24;
     uint16_t length;
     uint32_t xid;
-    uint32_t role;
+    enum ofp_controller_role role;
     pad(4);
     uint64_t generation_id;
 };
@@ -1410,5 +1529,7 @@
     uint8_t type == 25;
     uint16_t length;
     uint32_t xid;
-    of_octets_t data;
+    enum ofp_controller_role role;
+    pad(4);
+    uint64_t generation_id;
 };
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index 24129aa..db7ff0d 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -35,8 +35,8 @@
     OFP_MAX_TABLE_NAME_LEN = 32,
     OFP_MAX_PORT_NAME_LEN = 16,
 
-    OFP_TCP_PORT = 6633,
-    OFP_SSL_PORT = 6633,
+    OFP_TCP_PORT = 6653,
+    OFP_SSL_PORT = 6653,
 
     OFP_ETH_ALEN = 6,
 
@@ -58,10 +58,6 @@
     OFPQ_MIN_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_port_no(wire_type=uint32_t, complete=False) {
-    OFPP_ANY = 0xffffffff,
-};
-
 enum ofp_port(wire_type=uint32_t) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
@@ -71,6 +67,7 @@
     OFPP_ALL = 0xfffffffc,
     OFPP_CONTROLLER = 0xfffffffd,
     OFPP_LOCAL = 0xfffffffe,
+    OFPP_ANY = 0xffffffff,
 };
 
 enum ofp_type(wire_type=uint8_t) {
@@ -92,8 +89,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,
@@ -137,6 +134,7 @@
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
+    OFPPC_BSN_MIRROR_DEST = 0x80000000,
 };
 
 enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
@@ -250,6 +248,10 @@
     OFPFF_RESET_COUNTS = 0x4,
     OFPFF_NO_PKT_COUNTS = 0x8,
     OFPFF_NO_BYT_COUNTS = 0x10,
+
+    /* Non-standard, enabled by an experimenter message */
+    /* See the bsn_flow_idle input file */
+    OFPFF_BSN_SEND_IDLE = 0x80,
 };
 
 enum ofp_group(wire_type=uint32_t, complete=False) {
@@ -275,6 +277,13 @@
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
     OFPR_INVALID_TTL = 2,
+
+    // non-standard BSN extensions. OF does not have a standard-conformant
+    // way to extend the set of packet_in reasons
+    OFPR_BSN_NEW_HOST = 128,
+    OFPR_BSN_STATION_MOVE = 129,
+    OFPR_BSN_BAD_VLAN = 130,
+    OFPR_BSN_DESTINATION_LOOKUP_FAILURE = 131,
 };
 
 enum ofp_flow_removed_reason(wire_type=uint8_t) {
@@ -336,9 +345,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 +363,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 +385,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 +490,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 +704,7 @@
     uint8_t n_tables;
     uint8_t auxiliary_id;
     pad(2);
-    uint32_t capabilities;
+    enum ofp_capabilities capabilities;
     uint32_t reserved;
 };
 
@@ -725,7 +734,7 @@
 };
 
 // FIXME Does this need to be v4?
-struct of_match_v3(align=8) {
+struct of_match_v3(align=8, length_includes_align=False) {
     uint16_t type == 1;
     uint16_t length;
     list(of_oxm_t) oxm_list;
@@ -824,13 +833,13 @@
     pad(4);
 };
 
-struct of_action_set_field : of_action {
+struct of_action_set_field(align=8, length_includes_align=True) : of_action {
     uint16_t type == 25;
     uint16_t len;
     of_oxm_t field;
 };
 
-struct of_action_experimenter : of_action {
+struct of_action_experimenter(align=8, length_includes_align=True): of_action {
     uint16_t type == 65535;
     uint16_t len;
     uint32_t experimenter == ?;
@@ -1150,21 +1159,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
 
@@ -1244,7 +1391,7 @@
 
 struct of_group_desc_stats_entry {
     uint16_t length;
-    uint8_t type;
+    uint8_t group_type;
     pad(1);
     uint32_t group_id;
     list(of_bucket_t) buckets;
@@ -1259,7 +1406,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1269,7 +1416,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == ?;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
 };
 
@@ -1279,7 +1426,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1289,7 +1436,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 0;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     of_desc_str_t mfr_desc;
     of_desc_str_t hw_desc;
@@ -1304,7 +1451,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint8_t table_id;
     pad(3);
@@ -1322,7 +1469,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 1;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_flow_stats_entry_t) entries;
 };
@@ -1333,7 +1480,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint8_t table_id;
     pad(3);
@@ -1351,7 +1498,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 2;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     uint64_t packet_count;
     uint64_t byte_count;
@@ -1365,7 +1512,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1375,7 +1522,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 3;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_table_stats_entry_t) entries;
 };
@@ -1383,7 +1530,7 @@
 // FIXME: These are padded to 8 byte align beyond the length indicated
 
 struct of_table_feature_prop {
-    uint16_t         type;
+    uint16_t         type == ?;
     uint16_t         length;
 };
 
@@ -1516,7 +1663,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     of_port_no_t port_no;
     pad(4);
@@ -1528,7 +1675,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 4;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_port_stats_entry_t) entries;
 };
@@ -1539,7 +1686,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     of_port_no_t port_no;
     uint32_t queue_id;
@@ -1551,7 +1698,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 5;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_queue_stats_entry_t) entries;
 };
@@ -1562,7 +1709,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 6;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint32_t group_id;
     pad(4);
@@ -1574,7 +1721,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 6;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_group_stats_entry_t) entries;
 };
@@ -1585,7 +1732,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 7;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1595,7 +1742,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 7;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_group_desc_stats_entry_t) entries;
 };
@@ -1606,7 +1753,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 8;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1616,7 +1763,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 8;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     uint32_t types;
     uint32_t capabilities;
@@ -1636,7 +1783,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 9;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint32_t meter_id;
     pad(4);
@@ -1648,7 +1795,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 9;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_meter_stats_t) entries;
 };
@@ -1659,7 +1806,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 10;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     uint32_t meter_id;
     pad(4);
@@ -1671,7 +1818,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 10;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_meter_band_t) entries;
 };
@@ -1683,7 +1830,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 11;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1694,7 +1841,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 11;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     of_meter_features_t features;
 };
@@ -1706,7 +1853,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 12;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
     list(of_table_features_t) entries;
 };
@@ -1718,7 +1865,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 12;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_table_features_t) entries;
 };
@@ -1730,7 +1877,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 13;
-    uint16_t flags;
+    enum ofp_stats_request_flags flags;
     pad(4);
 };
 
@@ -1741,7 +1888,7 @@
     uint16_t length;
     uint32_t xid;
     uint16_t stats_type == 13;
-    uint16_t flags;
+    enum ofp_stats_reply_flags flags;
     pad(4);
     list(of_port_desc_t) entries;
 };
@@ -1770,7 +1917,7 @@
     list(of_meter_band_t) entries;
 };
 
-struct of_experimenter_multipart_header {
+struct of_experimenter_stats_header {
     uint32_t experimenter == ?;
     uint32_t subtype;
 };
@@ -1840,7 +1987,7 @@
     uint8_t type == 24;
     uint16_t length;
     uint32_t xid;
-    uint32_t role;
+    enum ofp_controller_role role;
     pad(4);
     uint64_t generation_id;
 };
@@ -1850,7 +1997,9 @@
     uint8_t type == 25;
     uint16_t length;
     uint32_t xid;
-    of_octets_t data;
+    enum ofp_controller_role role;
+    pad(4);
+    uint64_t generation_id;
 };
 
 ////////////////////////////////////////////////////////////////
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/__init__.py b/test_data/__init__.py
index 7a55c11..dc063fa 100644
--- a/test_data/__init__.py
+++ b/test_data/__init__.py
@@ -26,6 +26,7 @@
 # EPL for the specific language governing permissions and limitations
 # under the EPL.
 
+import fnmatch
 import os
 
 _test_data_dir = os.path.dirname(os.path.realpath(__file__))
@@ -45,6 +46,11 @@
                 result.append(dirname + '/' + filename)
     return sorted(result)
 
+def glob(pattern):
+    for f in list_files():
+        if fnmatch.fnmatch(f, pattern):
+            yield f
+
 def exists(name):
     return os.path.exists(os.path.join(_test_data_dir, name))
 
diff --git a/test_data/of13/action_output.data b/test_data/of13/action_output.data
index 7cd52ce..7653a30 100644
--- a/test_data/of13/action_output.data
+++ b/test_data/of13/action_output.data
@@ -6,3 +6,5 @@
 00 00 00 00 00 00 # pad
 -- python
 ofp.action.output(port=50, max_len=65535)
+-- java
+builder.setPort(OFPort.of(50)).setMaxLen(65535)
diff --git a/test_data/of13/action_set_field__bsn_lag_id.data b/test_data/of13/action_set_field__bsn_lag_id.data
new file mode 100644
index 0000000..f1a8aa1
--- /dev/null
+++ b/test_data/of13/action_set_field__bsn_lag_id.data
@@ -0,0 +1,11 @@
+-- binary
+00 19 # type
+00 10 # length
+00 03 02 04 # OXM header
+12 34 56 78 # OXM value
+00 00 00 00 # pad
+-- python
+ofp.action.set_field(field=ofp.oxm.bsn_lag_id(0x12345678))
+-- java
+OFOxms oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+builder.setField(oxms.bsnLagId(LagId.of(0x12345678)))
diff --git a/test_data/of13/action_set_field__eth_dst.data b/test_data/of13/action_set_field__eth_dst.data
new file mode 100644
index 0000000..833bb36
--- /dev/null
+++ b/test_data/of13/action_set_field__eth_dst.data
@@ -0,0 +1,11 @@
+-- binary
+00 19 # type
+00 10 # length
+80 00 06 06 # OXM header
+00 01 02 03 04 05 # OXM value
+00 00 # pad
+-- python
+ofp.action.set_field(field=ofp.oxm.eth_dst([0, 1, 2, 3, 4, 5]))
+-- java
+OFOxms oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+builder.setField(oxms.ethDst(MacAddress.of("00:01:02:03:04:05")))
diff --git a/test_data/of13/action_set_field_ipv6_src.data b/test_data/of13/action_set_field__ipv6_src.data
similarity index 60%
rename from test_data/of13/action_set_field_ipv6_src.data
rename to test_data/of13/action_set_field__ipv6_src.data
index f440dee..cfa2738 100644
--- a/test_data/of13/action_set_field_ipv6_src.data
+++ b/test_data/of13/action_set_field__ipv6_src.data
@@ -5,3 +5,6 @@
 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # OXM value
 -- python
 ofp.action.set_field(field=ofp.oxm.ipv6_src("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"))
+-- java
+OFOxms oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+builder.setField(oxms.ipv6Src(IPv6Address.of("0001:0203:0405:0607:0809:0a0b:0c0d:0e0f")))
diff --git a/test_data/of13/action_set_field__tcp_src.data b/test_data/of13/action_set_field__tcp_src.data
new file mode 100644
index 0000000..41c4780
--- /dev/null
+++ b/test_data/of13/action_set_field__tcp_src.data
@@ -0,0 +1,11 @@
+-- binary
+00 19 # type
+00 10 # length
+80 00 1a 02 # OXM header
+00 32 # OXM value
+00 00 00 00 00 00 # pad
+-- python
+ofp.action.set_field(field=ofp.oxm.tcp_src(50))
+-- java
+OFOxms oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+builder.setField(oxms.tcpSrc(TransportPort.of(50)))
diff --git a/test_data/of13/action_set_field_eth_dst.data b/test_data/of13/action_set_field_eth_dst.data
deleted file mode 100644
index 1e4a971..0000000
--- a/test_data/of13/action_set_field_eth_dst.data
+++ /dev/null
@@ -1,8 +0,0 @@
--- binary
-00 19 # type
-00 10 # length
-80 00 06 06 # OXM header
-00 01 02 03 04 05 # OXM value
-00 00 # pad
--- python
-ofp.action.set_field(field=ofp.oxm.eth_dst([0, 1, 2, 3, 4, 5]))
diff --git a/test_data/of13/action_set_field_tcp_src.data b/test_data/of13/action_set_field_tcp_src.data
deleted file mode 100644
index a69c7c0..0000000
--- a/test_data/of13/action_set_field_tcp_src.data
+++ /dev/null
@@ -1,8 +0,0 @@
--- binary
-00 19 # type
-00 10 # length
-80 00 1a 02 # OXM header
-00 32 # OXM value
-00 00 00 00 00 00 # pad
--- python
-ofp.action.set_field(field=ofp.oxm.tcp_src(50))
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/bsn_flow_idle.data b/test_data/of13/bsn_flow_idle.data
new file mode 100644
index 0000000..61b656f
--- /dev/null
+++ b/test_data/of13/bsn_flow_idle.data
@@ -0,0 +1,54 @@
+-- binary
+04 04 # version, type
+00 38 # length
+12 34 56 78 # xid
+00 5c 16 c7 # experimenter
+00 00 00 28 # subtype
+fe dc ba 98 76 54 32 10 # cookie
+42 68 # priority
+14 # table_id
+00 # pad
+00 00 00 00 # pad
+00 01 # match.type
+00 16 # match.length
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+80 00 2A 02 # match.oxm_list[1].type_len - ARP_OP
+00 01 # match.oxm_list[1].value
+00 00 # match.pad
+-- python
+ofp.message.bsn_flow_idle(
+    xid=0x12345678,
+    cookie=0xFEDCBA9876543210,
+    priority=17000,
+    table_id=20,
+    match=ofp.match([
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.arp_op(value=1),
+    ]))
+-- c
+obj = of_bsn_flow_idle_new(OF_VERSION_1_3);
+of_bsn_flow_idle_xid_set(obj, 0x12345678);
+of_bsn_flow_idle_cookie_set(obj, 0xFEDCBA9876543210);
+of_bsn_flow_idle_priority_set(obj, 17000);
+of_bsn_flow_idle_table_id_set(obj, 20);
+{
+    of_match_t match = { OF_VERSION_1_3 };
+    match.fields.in_port = 4;
+    match.masks.in_port = 5;
+    match.fields.arp_op = 1;
+    OF_MATCH_MASK_ARP_OP_EXACT_SET(&match);
+    of_bsn_flow_idle_match_set(obj, &match);
+}
+-- java
+builder.setXid(0x12345678)
+    .setCookie(U64.parseHex("FEDCBA9876543210"))
+    .setPriority(17000)
+    .setTableId(TableId.of(20))
+    .setMatch(
+        factory.buildMatch()
+            .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+            .setExact(MatchField.ARP_OP, ArpOpcode.of(1))
+                .build()
+    );
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/flow_add.data b/test_data/of13/flow_add.data
index 854c908..0766375 100644
--- a/test_data/of13/flow_add.data
+++ b/test_data/of13/flow_add.data
@@ -88,7 +88,7 @@
         factory.buildMatch()
             .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
             .setExact(MatchField.ETH_TYPE, EthType.IPv6)
-            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
             .setMasked(MatchField.IPV6_SRC, 
                        IPv6Address.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
                        IPv6Address.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
diff --git a/test_data/of13/flow_delete.data b/test_data/of13/flow_delete.data
index 497103f..6148d21 100644
--- a/test_data/of13/flow_delete.data
+++ b/test_data/of13/flow_delete.data
@@ -88,7 +88,7 @@
         factory.buildMatch()
             .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
             .setExact(MatchField.ETH_TYPE, EthType.IPv6)
-            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
             .setMasked(MatchField.IPV6_SRC, 
                        IPv6Address.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
                        IPv6Address.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
diff --git a/test_data/of13/flow_delete_strict.data b/test_data/of13/flow_delete_strict.data
index 83d212c..7e4d233 100644
--- a/test_data/of13/flow_delete_strict.data
+++ b/test_data/of13/flow_delete_strict.data
@@ -88,7 +88,7 @@
         factory.buildMatch()
             .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
             .setExact(MatchField.ETH_TYPE, EthType.IPv6)
-            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
             .setMasked(MatchField.IPV6_SRC, 
                        IPv6Address.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
                        IPv6Address.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
diff --git a/test_data/of13/flow_modify.data b/test_data/of13/flow_modify.data
index 9b8834d..83234f5 100644
--- a/test_data/of13/flow_modify.data
+++ b/test_data/of13/flow_modify.data
@@ -88,7 +88,7 @@
         factory.buildMatch()
             .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
             .setExact(MatchField.ETH_TYPE, EthType.IPv6)
-            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
             .setMasked(MatchField.IPV6_SRC, 
                        IPv6Address.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
                        IPv6Address.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
diff --git a/test_data/of13/flow_modify_strict.data b/test_data/of13/flow_modify_strict.data
index 250adb9..1d6f4c3 100644
--- a/test_data/of13/flow_modify_strict.data
+++ b/test_data/of13/flow_modify_strict.data
@@ -88,7 +88,7 @@
         factory.buildMatch()
             .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
             .setExact(MatchField.ETH_TYPE, EthType.IPv6)
-            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
             .setMasked(MatchField.IPV6_SRC, 
                        IPv6Address.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
                        IPv6Address.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
diff --git a/test_data/of13/group_desc_stats_reply.data b/test_data/of13/group_desc_stats_reply.data
index 34c0d50..5e95a67 100644
--- a/test_data/of13/group_desc_stats_reply.data
+++ b/test_data/of13/group_desc_stats_reply.data
@@ -49,7 +49,7 @@
     flags=0,
     entries=[
         ofp.group_desc_stats_entry(
-            type=ofp.OFPGT_FF,
+            group_type=ofp.OFPGT_FF,
             group_id=1,
             buckets=[
                 ofp.bucket(
@@ -66,4 +66,4 @@
                     actions=[
                         ofp.action.output(port=5, max_len=0),
                         ofp.action.output(port=6, max_len=0)])]),
-        ofp.group_desc_stats_entry(type=ofp.OFPGT_FF, group_id=2, buckets=[])])
+        ofp.group_desc_stats_entry(group_type=ofp.OFPGT_FF, group_id=2, buckets=[])])
diff --git a/test_data/of13/oxm_bsn_global_vrf_allowed.data b/test_data/of13/oxm_bsn_global_vrf_allowed.data
new file mode 100644
index 0000000..d5fe8d7
--- /dev/null
+++ b/test_data/of13/oxm_bsn_global_vrf_allowed.data
@@ -0,0 +1,12 @@
+-- binary
+00 03 # class
+06 # type/masked
+01 # length
+01 # value
+-- python
+ofp.oxm.bsn_global_vrf_allowed(1)
+-- c
+obj = of_oxm_bsn_global_vrf_allowed_new(OF_VERSION_1_3);
+of_oxm_bsn_global_vrf_allowed_value_set(obj, 1);
+-- java
+builder.setValue(OFBooleanValue.TRUE)
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());
diff --git a/test_data/of13/oxm_bsn_l3_src_class_id.data b/test_data/of13/oxm_bsn_l3_src_class_id.data
new file mode 100644
index 0000000..5da07e3
--- /dev/null
+++ b/test_data/of13/oxm_bsn_l3_src_class_id.data
@@ -0,0 +1,12 @@
+-- binary
+00 03 # class
+0a # type/masked
+04 # length
+12 34 56 78 # value
+-- python
+ofp.oxm.bsn_l3_src_class_id(0x12345678)
+-- c
+obj = of_oxm_bsn_l3_src_class_id_new(OF_VERSION_1_3);
+of_oxm_bsn_l3_src_class_id_value_set(obj, 0x12345678);
+-- java
+builder.setValue(ClassId.of(0x12345678))
diff --git a/test_data/of13/oxm_bsn_lag_id.data b/test_data/of13/oxm_bsn_lag_id.data
new file mode 100644
index 0000000..e8b2fcd
--- /dev/null
+++ b/test_data/of13/oxm_bsn_lag_id.data
@@ -0,0 +1,12 @@
+-- binary
+00 03 # class
+02 # type/masked
+04 # length
+12 34 56 78 # value
+-- python
+ofp.oxm.bsn_lag_id(0x12345678)
+-- c
+obj = of_oxm_bsn_lag_id_new(OF_VERSION_1_3);
+of_oxm_bsn_lag_id_value_set(obj, 0x12345678);
+-- java
+builder.setValue(LagId.of(0x12345678))
diff --git a/test_data/of13/packet_in.data b/test_data/of13/packet_in.data
index ca7006f..525d144 100644
--- a/test_data/of13/packet_in.data
+++ b/test_data/of13/packet_in.data
@@ -41,7 +41,7 @@
    .setMatch(
         factory.buildMatchV3()
             .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
-            .setExact(MatchField.ARP_OP, ArpOpcode.ARP_OPCODE_REQUEST)
+            .setExact(MatchField.ARP_OP, ArpOpcode.REQUEST)
         	.build()
     )
     .setData(new byte[] { 97, 98, 99 } );
diff --git a/wireshark_gen/__init__.py b/wireshark_gen/__init__.py
new file mode 100644
index 0000000..c4ff7f4
--- /dev/null
+++ b/wireshark_gen/__init__.py
@@ -0,0 +1,118 @@
+# 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.
+
+import os
+from collections import namedtuple
+import loxi_utils.loxi_utils as utils
+import loxi_front_end
+import of_g
+from loxi_ir import *
+import field_info
+
+templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
+
+DissectorField = namedtuple("DissectorField", ["fullname", "name", "type", "base", "enum_table"])
+
+proto_names = { 1: 'of10', 2: 'of11', 3: 'of12', 4: 'of13' }
+def make_field_name(wire_version, ofclass_name, member_name):
+    return "%s.%s.%s" % (proto_names[wire_version],
+                         ofclass_name[3:],
+                         member_name)
+
+def get_reader(version, cls, m):
+    """
+    Decide on a reader function to use for the given field
+    """
+    ofproto = of_g.ir[version]
+    enum = ofproto.enum_by_name(m.oftype)
+    if enum and 'wire_type' in enum.params:
+        return "read_" + enum.params['wire_type']
+    else:
+        return "read_" + m.oftype.replace(')', '').replace('(', '_')
+
+def get_field_info(version, cls, name, oftype):
+    """
+    Decide on a Wireshark type and base for a given field.
+
+    Returns (type, base)
+    """
+    if oftype.startswith("list"):
+        return "bytes", "NONE", "nil"
+
+    ofproto = of_g.ir[version]
+
+    enum = ofproto.enum_by_name(oftype)
+    if not enum and (cls, name) in field_info.class_field_to_enum:
+        enum_name = field_info.class_field_to_enum[(cls, name)]
+        enum = ofproto.enum_by_name(enum_name)
+
+    if enum:
+        field_type = "uint32"
+    elif oftype in field_info.oftype_to_wireshark_type:
+        field_type = field_info.oftype_to_wireshark_type[oftype]
+    else:
+        print "WARN missing oftype_to_wireshark_type for", oftype
+        field_type = "bytes"
+
+    if enum:
+        if enum.is_bitmask:
+            field_base = "HEX"
+        else:
+            field_base = "DEC"
+    elif oftype in field_info.field_to_base:
+        field_base = field_info.field_to_base[name]
+    elif oftype in field_info.oftype_to_base:
+        field_base = field_info.oftype_to_base[oftype]
+    else:
+        print "WARN missing oftype_to_base for", oftype
+        field_base = "NONE"
+
+    if enum:
+        enum_table = 'enum_v%d_%s' % (version, enum.name)
+    else:
+        enum_table = 'nil'
+
+    return field_type, field_base, enum_table
+
+def create_fields():
+    r = []
+    for wire_version, ofproto in of_g.ir.items():
+        for ofclass in ofproto.classes:
+            for m in ofclass.members:
+                if isinstance(m, OFPadMember):
+                    continue
+                fullname = make_field_name(wire_version, ofclass.name, m.name)
+                field_type, field_base, enum_table = get_field_info(wire_version, ofclass.name, m.name, m.oftype)
+                r.append(DissectorField(fullname, m.name, field_type, field_base, enum_table))
+
+    return r
+
+def generate(out, name):
+    context = {
+        'fields': create_fields(),
+    }
+    utils.render_template(out, "openflow.lua", [templates_dir], context)
diff --git a/wireshark_gen/field_info.py b/wireshark_gen/field_info.py
new file mode 100644
index 0000000..4a80a8e
--- /dev/null
+++ b/wireshark_gen/field_info.py
@@ -0,0 +1,126 @@
+# 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.
+
+# Map from LOXI types to Wireshark types
+oftype_to_wireshark_type = {
+    "char": "int8",
+    "uint8_t": "uint8",
+    "uint16_t": "uint16",
+    "uint32_t": "uint32",
+    "uint64_t": "uint64",
+    "of_mac_addr_t": "ether",
+    "of_ipv4_t": "ipv4",
+    "of_ipv6_t": "ipv6",
+    "of_port_name_t": "stringz",
+    "of_table_name_t": "stringz",
+    "of_desc_str_t": "stringz",
+    "of_serial_num_t": "stringz",
+    "of_octets_t": "bytes",
+    "of_port_no_t": "uint32",
+    "of_port_desc_t": "stringz",
+    "of_bsn_vport_t": "bytes",
+    "of_bsn_vport_q_in_q_t": "bytes",
+    "of_fm_cmd_t": "uint16",
+    "of_wc_bmap_t": "uint64",
+    "of_match_bmap_t": "uint64",
+    "of_match_t": "bytes",
+    "of_oxm_t": "bytes",
+    "of_meter_features_t": "bytes",
+    "of_bitmap_128_t": "bytes",
+}
+
+# Map from LOXI type to Wireshark base
+oftype_to_base = {
+    "char": "DEC",
+    "uint8_t": "DEC",
+    "uint16_t": "DEC",
+    "uint32_t": "DEC",
+    "uint64_t": "DEC",
+    "of_mac_addr_t": "NONE",
+    "of_ipv4_t": "NONE",
+    "of_ipv6_t": "NONE",
+    "of_port_name_t": "NONE",
+    "of_table_name_t": "NONE",
+    "of_desc_str_t": "NONE",
+    "of_serial_num_t": "NONE",
+    "of_octets_t": "NONE",
+    "of_port_no_t": "DEC",
+    "of_port_desc_t": "NONE",
+    "of_bsn_vport_t": "NONE",
+    "of_bsn_vport_q_in_q_t": "NONE",
+    "of_fm_cmd_t": "DEC",
+    "of_wc_bmap_t": "HEX",
+    "of_match_bmap_t": "HEX",
+    "of_match_t": "NONE",
+    "of_oxm_t": "NONE",
+    "of_meter_features_t": "NONE",
+    "of_bitmap_128_t": "NONE",
+}
+
+# Use enums for certain fields where it isn't specified in the LOXI input
+class_field_to_enum = {
+    ('of_flow_mod', 'type'): 'ofp_type',
+    ('of_error_msg', 'type'): 'ofp_type',
+    ('of_stats_request', 'type'): 'ofp_type',
+    ('of_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_stats_request', 'flags'): 'ofp_stats_request_flags',
+    ('of_stats_reply', 'type'): 'ofp_type',
+    ('of_stats_reply', 'stats_type'): 'ofp_stats_type',
+    ('of_stats_reply', 'flags'): 'ofp_stats_reply_flags',
+    ('of_flow_mod', 'table_id'): 'ofp_table',
+    ('of_flow_mod', '_command'): 'ofp_flow_mod_command',
+    ('of_flow_mod', 'out_port'): 'ofp_port',
+    ('of_flow_mod', 'out_group'): 'ofp_group',
+    ('of_error_msg', 'err_type'): 'ofp_error_type',
+    ('of_port_mod', 'type'): 'ofp_type',
+    ('of_hello', 'type'): 'ofp_type',
+    ('of_features_request', 'type'): 'ofp_type',
+    ('of_features_reply', 'type'): 'ofp_type',
+    ('of_barrier_request', 'type'): 'ofp_type',
+    ('of_barrier_reply', 'type'): 'ofp_type',
+    ('of_echo_request', 'type'): 'ofp_type',
+    ('of_echo_reply', 'type'): 'ofp_type',
+    ('of_match_v3', 'type'): 'ofp_match_type',
+    ('of_action_set_nw_ttl', 'type'): 'ofp_action_type',
+    ('of_action_output', 'type'): 'ofp_action_type',
+    ('of_action_group', 'type'): 'ofp_action_type',
+    ('of_action_id', 'type'): 'ofp_action_type',
+    ('of_instruction_apply_actions', 'type'): 'ofp_instruction_type',
+    ('of_instruction_write_actions', 'type'): 'ofp_instruction_type',
+    ('of_group_mod', 'group_type'): 'ofp_group_type',
+    ('of_group_mod', 'type'): 'ofp_type',
+    ('of_group_mod', 'command'): 'ofp_group_mod_commane',
+    ('of_group_mod', 'group_id'): 'ofp_group',
+
+}
+
+# Override oftype_to_base for certain field names
+field_to_base = {
+    "eth_type": "HEX",
+    "cookie": "HEX",
+    "datapath_id": "HEX",
+}
diff --git a/wireshark_gen/templates/.gitignore b/wireshark_gen/templates/.gitignore
new file mode 100644
index 0000000..c3ed10e
--- /dev/null
+++ b/wireshark_gen/templates/.gitignore
@@ -0,0 +1 @@
+*.cache
diff --git a/wireshark_gen/templates/_copyright.lua b/wireshark_gen/templates/_copyright.lua
new file mode 100644
index 0000000..8700ad3
--- /dev/null
+++ b/wireshark_gen/templates/_copyright.lua
@@ -0,0 +1,42 @@
+:: # 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.
+::
+-- Copyright 2013, Big Switch Networks, Inc. This library was generated
+-- by the LoxiGen Compiler.
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 2 of the License, or
+-- (at your option) any later version.
+-- 
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+-- 
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/wireshark_gen/templates/_ofclass_dissector.lua b/wireshark_gen/templates/_ofclass_dissector.lua
new file mode 100644
index 0000000..4aef886
--- /dev/null
+++ b/wireshark_gen/templates/_ofclass_dissector.lua
@@ -0,0 +1,52 @@
+:: # 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.
+::
+:: from loxi_ir import *
+:: from wireshark_gen import make_field_name, get_reader
+:: attrs = []
+:: if ofclass.virtual: attrs.append("virtual")
+:: if ofclass.superclass: attrs.append("child")
+:: if not ofclass.superclass: attrs.append("top-level")
+-- ${' '.join(attrs)} class ${ofclass.name}
+:: if ofclass.superclass:
+-- Child of ${ofclass.superclass}
+:: #endif
+:: if ofclass.virtual:
+-- Discriminator is ${ofclass.discriminator.name}
+:: #endif
+function ${name}(reader, subtree)
+:: for m in ofclass.members:
+:: if isinstance(m, OFPadMember):
+    reader.skip(${m.length})
+:: continue
+:: #endif
+:: field_name = make_field_name(version, ofclass.name, m.name)
+:: reader_name = get_reader(version, ofclass, m)
+    ${reader_name}(reader, ${version}, subtree, '${field_name}')
+:: #endfor
+    return '${ofclass.name}'
+end
diff --git a/wireshark_gen/templates/_ofreader.lua b/wireshark_gen/templates/_ofreader.lua
new file mode 100644
index 0000000..a4c57be
--- /dev/null
+++ b/wireshark_gen/templates/_ofreader.lua
@@ -0,0 +1,72 @@
+:: # 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.
+::
+OFReader = {}
+OFReader.new = function(buf, offset)
+    local self = {}
+    offset = offset or 0
+
+    self.read = function(len)
+        local r = buf(offset, len)
+        offset = offset + len
+        return r
+    end
+
+    self.read_all = function()
+        local r = buf(offset, buf:len() - offset)
+        offset = buf:len()
+        return r
+    end
+
+    self.peek = function(off, len)
+        return buf(offset + off, len)
+    end
+
+    self.peek_all = function(off)
+        return buf(offset + off, buf:len() - offset - off)
+    end
+
+    self.skip = function(len)
+        offset = offset + len
+    end
+
+    self.is_empty = function()
+        return offset == buf:len()
+    end
+
+    self.slice = function(len)
+        r = OFReader.new(buf(offset, len))
+        offset = offset + len
+        return r
+    end
+    
+    self.skip_align = function()
+        offset = math.floor((offset + 7)/8)*8
+    end
+
+    return self
+end
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
new file mode 100644
index 0000000..4f5d7f9
--- /dev/null
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -0,0 +1,181 @@
+:: # 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.
+
+function read_scalar(reader, subtree, field_name, length)
+    subtree:add(fields[field_name], reader.read(length))
+end
+
+function read_uint8_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 1)
+end
+
+function read_uint16_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 2)
+end
+
+function read_uint32_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 4)
+end
+
+function read_uint64_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 8)
+end
+
+function read_of_octets_t(reader, version, subtree, field_name)
+    if not reader.is_empty() then
+        subtree:add(fields[field_name], reader.read_all())
+    end
+end
+
+function read_list_of_hello_elem_t(reader, version, subtree, field_name)
+    -- TODO
+end
+
+function read_of_match_t(reader, version, subtree, field_name)
+    if version == 1 then
+        dissect_of_match_v1_v1(reader, subtree:add(fields[field_name]))
+    elseif version == 2 then
+        dissect_of_match_v2_v2(reader, subtree:add(fields[field_name]))
+    elseif version >= 3 then
+        dissect_of_match_v3_v3(reader, subtree:add(fields[field_name]))
+    end
+end
+
+function read_of_wc_bmap_t(reader, version, subtree, field_name)
+    if version <= 2 then
+        read_scalar(reader, subtree, field_name, 4)
+    else
+        read_scalar(reader, subtree, field_name, 8)
+    end
+end
+
+function read_of_port_no_t(reader, version, subtree, field_name)
+    if version == 1 then
+        read_scalar(reader, subtree, field_name, 2)
+    else
+        read_scalar(reader, subtree, field_name, 4)
+    end
+end
+
+function read_of_mac_addr_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 6)
+end
+
+function read_of_ipv4_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 4)
+end
+
+function read_of_ipv6_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 16)
+end
+
+function read_of_fm_cmd_t(reader, version, subtree, field_name)
+    if version == 1 then
+        read_scalar(reader, subtree, field_name, 2)
+    else
+        read_scalar(reader, subtree, field_name, 1)
+    end
+end
+
+function read_list_of_action_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+
+    local list = subtree:add(fields[field_name], reader.peek_all(0))
+    while not reader.is_empty() do
+        local action_len = reader.peek(2, 2):uint()
+        local child_reader = reader.slice(action_len)
+        local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_action(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
+    list:set_text("List of actions")
+end
+
+function read_list_of_port_desc_t(reader, version, subtree, field_name)
+    -- TODO
+end
+
+function read_list_of_packet_queue_t(reader, version, subtree, field_name)
+    -- TODO
+end
+
+function read_list_of_oxm_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local list_len = reader.peek(-2,2):uint()
+    local reader2 = reader.slice(list_len - 4)
+    local list = nil
+    if not reader2.is_empty() then
+        list = subtree:add(fields[field_name], reader2.peek_all(0))
+        list:set_text("List of matches")
+    end
+    while not reader2.is_empty() do
+        local match_len = 4 + reader2.peek(3,1):uint()
+        local child_reader = reader2.slice(match_len)
+        local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_oxm(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
+    subtree:set_text("OXM")
+    reader.skip_align()
+end
+
+function read_list_of_instruction_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local child_subtree = subtree:add(fields[field_name], reader.peek_all(0))
+    local info = dissect_of_instruction(reader, child_subtree, version)
+    child_subtree:set_text("Instructions")
+end
+
+function read_list_of_bucket_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local bucket_list_subtree = subtree:add(fields[field_name], reader.peek_all(0))
+    bucket_list_subtree:set_text("List of buckets")
+    while not reader.is_empty() do
+        local bucket_len = reader.peek(0,2):uint()
+        local child_reader = reader.slice(bucket_len)
+        local child_subtree = bucket_list_subtree:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_bucket(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
+end
+
+function read_of_oxm_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local child_subtree = subtree:add(fields[field_name], reader.peek_all(0))
+    local info = dissect_of_oxm(reader, child_subtree, version)
+    child_subtree:set_text(info)
+end
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
new file mode 100644
index 0000000..f2791d1
--- /dev/null
+++ b/wireshark_gen/templates/openflow.lua
@@ -0,0 +1,225 @@
+:: # 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.
+::
+:: import of_g
+:: ir = of_g.ir
+:: include('_copyright.lua')
+
+:: include('_ofreader.lua')
+
+:: include('_oftype_readers.lua')
+
+p_of = Proto ("of", "OpenFlow")
+
+local openflow_versions = {
+:: for (version, name) in of_g.param_version_names.items():
+    [${version}] = "${name}",
+:: #endfor
+}
+
+:: for version, ofproto in ir.items():
+:: for enum in ofproto.enums:
+local enum_v${version}_${enum.name} = {
+:: for (name, value) in enum.values:
+    [${value}] = "${name}",
+:: #endfor
+}
+
+:: #endfor
+
+:: #endfor
+
+
+fields = {}
+:: for field in fields:
+:: if field.type in ["uint8", "uint16", "uint32", "uint64"]:
+fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}", base.${field.base}, ${field.enum_table})
+:: elif field.type in ["ipv4", "ipv6", "ether", "bytes", "stringz"]:
+fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}")
+:: else:
+:: raise NotImplementedError("unknown Wireshark type " + field.type)
+:: #endif
+:: #endfor
+
+p_of.fields = {
+:: for field in fields:
+    fields[${repr(field.fullname)}],
+:: #endfor
+}
+
+-- Subclass maps for virtual classes
+:: for version, ofproto in ir.items():
+:: for ofclass in ofproto.classes:
+:: if ofclass.virtual:
+${ofclass.name}_v${version}_dissectors = {}
+:: #endif
+:: #endfor
+:: #endfor
+
+--- Dissectors for each class
+
+:: for version, ofproto in ir.items():
+:: for ofclass in ofproto.classes:
+:: name = 'dissect_%s_v%d' % (ofclass.name, version)
+:: include('_ofclass_dissector.lua', name=name, ofclass=ofclass, version=version)
+:: if ofclass.superclass:
+:: discriminator = ofproto.class_by_name(ofclass.superclass).discriminator
+:: discriminator_value = ofclass.member_by_name(discriminator.name).value
+${ofclass.superclass}_v${version}_dissectors[${discriminator_value}] = ${name}
+
+:: #endif
+:: #endfor
+:: #endfor
+
+local of_message_dissectors = {
+:: for version in ir:
+    [${version}] = of_header_v${version}_dissectors,
+:: #endfor
+}
+
+local of_oxm_dissectors = {
+:: for version in ir:
+    [${version}] = of_oxm_v${version}_dissectors,
+:: #endfor
+}
+
+local of_action_dissectors = {
+:: for version in ir:
+    [${version}] = of_action_v${version}_dissectors,
+:: #endfor
+}
+
+local of_instruction_dissectors = {
+:: for version in ir:
+    [${version}] = of_instruction_v${version}_dissectors,
+:: #endfor
+}
+
+local of_bucket_dissectors = {
+:: for version in ir:
+    [${version}] = dissect_of_bucket_v${version},
+:: #endfor
+}
+
+function dissect_of_message(buf, root)
+    local reader = OFReader.new(buf)
+    local subtree = root:add(p_of, buf(0))
+    local version_val = buf(0,1):uint()
+    local type_val = buf(1,1):uint()
+
+    local protocol = "OF ?"
+    if openflow_versions[version_val] then
+        protocol = "OF " .. openflow_versions[version_val]
+    end
+
+    local info = "unknown"
+    if of_message_dissectors[version_val] and of_message_dissectors[version_val][type_val] then
+        info = of_message_dissectors[version_val][type_val](reader, subtree)
+    end
+
+    return protocol, info
+end
+
+function dissect_of_oxm(reader, subtree, version_val)
+    local type_val = reader.peek(0,4):uint()
+    local info = "unknown"
+    if of_oxm_dissectors[version_val] and of_oxm_dissectors[version_val][type_val] then
+        info = of_oxm_dissectors[version_val][type_val](reader, subtree)
+    end
+
+    return info
+end
+
+function dissect_of_action(reader, subtree, version_val)
+    local type_val = reader.peek(0,2):uint()
+    local info = "unknown"
+    if of_action_dissectors[version_val] and of_action_dissectors[version_val][type_val] then
+        info = of_action_dissectors[version_val][type_val](reader, subtree)
+    end
+
+    return info
+end
+
+function dissect_of_instruction(reader, subtree, version_val)
+    local type_val = reader.peek(0,2):uint()
+    local info = "unknown"
+    if of_instruction_dissectors[version_val] and of_instruction_dissectors[version_val][type_val] then
+        info = of_instruction_dissectors[version_val][type_val](reader, subtree)
+    end
+
+    return info
+end
+
+function dissect_of_bucket(reader, subtree, version_val)
+    local info = "unknown"
+    if of_bucket_dissectors[version_val] then
+        info = of_bucket_dissectors[version_val](reader, subtree)
+    end
+
+    return info
+end
+
+-- of dissector function
+function p_of.dissector (buf, pkt, root)
+    local offset = 0
+    repeat
+        if buf:len() - offset >= 4 then
+            msg_len = buf(offset+2,2):uint()
+            if offset + msg_len > buf:len() then
+                -- we don't have all the data we need yet
+                pkt.desegment_len = offset + msg_len - buf:len()
+                return
+            end
+
+            protocol, info = dissect_of_message(buf(offset, msg_len), root)
+
+            if offset == 0 then
+                pkt.cols.protocol:clear()
+                pkt.cols.info:clear()
+            else
+                pkt.cols.protocol:append(" + ")
+                pkt.cols.info:append(" + ")
+            end
+            pkt.cols.protocol:append(protocol)
+            pkt.cols.info:append(info)
+            offset = offset + msg_len
+        else
+            -- we don't have all of length field yet
+            pkt.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
+            return
+        end
+    until offset >= buf:len()
+end
+
+-- Initialization routine
+function p_of.init()
+end
+
+-- register a chained dissector for OpenFlow port numbers
+local tcp_dissector_table = DissectorTable.get("tcp.port")
+tcp_dissector_table:add(6633, p_of)
+tcp_dissector_table:add(6653, p_of)