diff --git a/scapy/contrib/openflow.py b/scapy/contrib/openflow.py
new file mode 100755
index 0000000000000000000000000000000000000000..beab1f13158b812e9e43897728c99703c03679b4
--- /dev/null
+++ b/scapy/contrib/openflow.py
@@ -0,0 +1,1213 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more information
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+## Copyright (C) 2014 Maxence Tury <maxence.tury@ssi.gouv.fr>
+## OpenFlow is an open standard used in SDN deployments.
+## Based on OpenFlow v1.0.1
+## Specifications can be retrieved from https://www.opennetworking.org/
+
+# scapy.contrib.description = openflow v1.0
+# scapy.contrib.status = loads
+
+import binascii
+import struct
+from scapy.all import *
+
+### If prereq_autocomplete is True then match prerequisites will be
+### automatically handled. See OFPMatch class.
+prereq_autocomplete = False
+
+#####################################################
+################# Predefined values #################
+#####################################################
+
+ofp_port_no = { 0xfff8: "IN_PORT",
+                0xfff9: "TABLE",
+                0xfffa: "NORMAL",
+                0xfffb: "FLOOD",
+                0xfffc: "ALL",
+                0xfffd: "CONTROLLER",
+                0xfffe: "LOCAL",
+                0xffff: "NONE" }
+
+ofp_table = { 0xff: "ALL" }
+
+ofp_queue = { 0xffffffff: "ALL" }
+
+ofp_buffer = { 0xffffffff: "NO_BUFFER" }
+
+ofp_max_len = { 0xffff: "NO_BUFFER" }
+
+#####################################################
+################# Common structures #################
+#####################################################
+
+### The following structures will be used in different types
+### of OpenFlow messages: ports, matches, actions, queues.
+
+
+##################### Ports #####################
+
+ofp_port_config = [ "PORT_DOWN",
+                    "NO_STP",
+                    "NO_RECV",
+                    "NO_RECV_STP",
+                    "NO_FLOOD",
+                    "NO_FWD",
+                    "NO_PACKET_IN" ]
+
+ofp_port_state = [ "LINK_DOWN" ]
+
+ofp_port_state_stp = { 0: "OFPPS_STP_LISTEN",
+                       1: "OFPPS_STP_LEARN",
+                       2: "OFPPS_STP_FORWARD",
+                       3: "OFPPS_STP_BLOCK" }
+
+ofp_port_features = [ "10MB_HD",
+                      "10MB_FD",
+                      "100MB_HD",
+                      "100MB_FD",
+                      "1GB_HD",
+                      "1GB_FD",
+                      "10GB_FD",
+                      "COPPER",
+                      "FIBER",
+                      "AUTONEG",
+                      "PAUSE",
+                      "PAUSE_ASYM" ]
+
+class OFPPhyPort(Packet):
+    name = "OFP_PHY_PORT"
+    fields_desc = [ ShortEnumField("port_no", 0, ofp_port_no),
+                    MACField("hw_addr", "0"),
+                    StrFixedLenField("port_name", "", 16),
+                    FlagsField("config", 0, 32, ofp_port_config),
+                    BitEnumField("stp_state", 0, 24, ofp_port_state),
+                    FlagsField("state", 0, 8, ofp_port_state),
+                    FlagsField("curr", 0, 32, ofp_port_features),
+                    FlagsField("advertised", 0, 32, ofp_port_features),
+                    FlagsField("supported", 0, 32, ofp_port_features),
+                    FlagsField("peer", 0, 32, ofp_port_features) ]
+
+    def extract_padding(self, s):
+        return "", s
+
+class OFPMatch(Packet):
+    name = "OFP_MATCH"
+    fields_desc= [ FlagsField("wildcards1", None, 12, [ "DL_VLAN_PCP",
+                                                        "NW_TOS" ]),
+                   BitField("nw_dst_mask", None, 6),
+                   BitField("nw_src_mask", None, 6),
+                   FlagsField("wildcards2", None, 8, [ "IN_PORT",
+                                                       "DL_VLAN",
+                                                       "DL_SRC",
+                                                       "DL_DST",
+                                                       "DL_TYPE",
+                                                       "NW_PROTO",
+                                                       "TP_SRC",
+                                                       "TP_DST" ]),
+                   ShortEnumField("in_port", None, ofp_port_no),
+                   MACField("dl_src", None),
+                   MACField("dl_dst", None),
+                   ShortField("dl_vlan", None),
+                   ByteField("dl_vlan_pcp", None),
+                   XByteField("pad1", None),
+                   ShortField("dl_type", None),
+                   ByteField("nw_tos", None),
+                   ByteField("nw_proto", None),
+                   XShortField("pad2", None),
+                   IPField("nw_src", "0"),
+                   IPField("nw_dst", "0"),
+                   ShortField("tp_src", None),
+                   ShortField("tp_dst", None) ]
+
+    def extract_padding(self, s):
+        return "", s
+
+    ### with post_build we create the wildcards field bit by bit
+    def post_build(self, p, pay):
+        # first 10 bits of an ofp_match are always set to 0
+        l = ["0"*10]
+
+        # when one field has not been declared, it is assumed to be wildcarded
+        if self.wildcards1 is None:
+            if self.nw_tos is None: l.append("1")
+            else: l.append("0")
+            if self.dl_vlan_pcp is None: l.append("1")
+            else: l.append("0")
+        else:
+            w1 = bin(self.wildcards1)[2:]
+            l.append("0"*(2-len(w1)))
+            l.append(w1)
+                    
+        # ip masks use 6 bits each
+        if self.nw_dst_mask is None:
+            if self.nw_dst is "0": l.append("111111")
+            # 0x100000 would be ok too (32-bit IP mask)
+            else: l.append("0"*6)
+        else:
+            m1 = bin(self.nw_dst_mask)[2:]
+            l.append("0"*(6-len(m1)))
+            l.append(m1)
+        if self.nw_src_mask is None:
+            if self.nw_src is "0": l.append("111111")
+            else: l.append("0"*6)
+        else:
+            m2 = bin(self.nw_src_mask)[2:]
+            l.append("0"*(6-len(m2)))
+            l.append(m2)
+
+        # wildcards2 works the same way as wildcards1
+        if self.wildcards2 is None:
+            if self.tp_dst is None: l.append("1")
+            else: l.append("0")
+            if self.tp_src is None: l.append("1")
+            else: l.append("0")
+            if self.nw_proto is None: l.append("1")
+            else: l.append("0")
+            if self.dl_type is None: l.append("1")
+            else: l.append("0")
+            if self.dl_dst is None: l.append("1")
+            else: l.append("0")
+            if self.dl_src is None: l.append("1")
+            else: l.append("0")
+            if self.dl_vlan is None: l.append("1")
+            else: l.append("0")
+            if self.in_port is None: l.append("1")
+            else: l.append("0")
+        else:
+            w2 = bin(self.wildcards2)[2:]
+            l.append("0"*(8-len(w2)))
+            l.append(w2)
+
+        ### In order to write OFPMatch compliant with the specifications,
+        ### if prereq_autocomplete has been set to True
+        ### we assume ethertype=IP or nwproto=TCP when appropriate subfields are provided.
+        if prereq_autocomplete:
+            if self.dl_type is None:
+                if self.nw_src is not "0" or self.nw_dst is not "0" or self.nw_proto is not None or self.nw_tos is not None:
+                    p = p[:22] + struct.pack("!H", 0x0800) + p[24:]
+                    l[-5] = "0"
+            if self.nw_proto is None:
+                if self.tp_src is not None or self.tp_dst is not None:
+                    p = p[:22] + struct.pack("!H", 0x0800) + p[24:]
+                    l[-5] = "0"
+                    p = p[:25] + struct.pack("!B", 0x06) + p[26:]
+                    l[-6] = "0"
+
+        wild = "".join(l)
+        pad = ""
+        i = 0
+        while i < 32 and wild[i:i+4] == "0000":
+                    pad += "0"
+                    i += 4
+        ins = binascii.unhexlify(pad + "%x" % int(wild, 2))
+        p = ins + p[4:]
+        return p + pay
+
+
+###################### Actions ######################
+
+class _ofp_action_header(Packet):
+    name = "Dummy OpenFlow Action Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+ofp_action_types = {     0: "OFPAT_OUTPUT",
+                         1: "OFPAT_SET_VLAN_VID",
+                         2: "OFPAT_SET_VLAN_PCP",
+                         3: "OFPAT_STRIP_VLAN",
+                         4: "OFPAT_SET_DL_SRC",
+                         5: "OFPAT_SET_DL_DST",
+                         6: "OFPAT_SET_NW_SRC",
+                         7: "OFPAT_SET_NW_DST",
+                         8: "OFPAT_SET_NW_TOS",
+                         9: "OFPAT_SET_TP_SRC",
+                        10: "OFPAT_SET_TP_DST",
+                        11: "OFPAT_ENQUEUE",
+                     65535: "OFPAT_VENDOR" }
+
+class OFPATOutput(_ofp_action_header):
+    name = "OFPAT_OUTPUT"
+    fields_desc = [ ShortEnumField("type", 0, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortEnumField("port", 0, ofp_port_no),
+                    ShortEnumField("max_len", "NO_BUFFER", ofp_max_len) ]
+
+class OFPATSetVLANVID(_ofp_action_header):
+    name = "OFPAT_SET_VLAN_VID"
+    fields_desc = [ ShortEnumField("type", 1, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("vlan_vid", 0),
+                    XShortField("pad", 0) ]
+
+class OFPATSetVLANPCP(_ofp_action_header):
+    name = "OFPAT_SET_VLAN_PCP"
+    fields_desc = [ ShortEnumField("type", 2, ofp_action_types),
+                    ShortField("len", 8),
+                    ByteField("vlan_pcp", 0),
+                    X3BytesField("pad", 0) ]
+
+class OFPATStripVLAN(_ofp_action_header):
+    name = "OFPAT_STRIP_VLAN"
+    fields_desc = [ ShortEnumField("type", 3, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATSetDlSrc(_ofp_action_header):
+    name = "OFPAT_SET_DL_SRC"
+    fields_desc = [ ShortEnumField("type", 4, ofp_action_types),
+                    ShortField("len", 16),
+                    MACField("dl_addr", "0"),
+                    XBitField("pad", 0, 48) ]
+
+class OFPATSetDlDst(_ofp_action_header):
+    name = "OFPAT_SET_DL_DST"
+    fields_desc = [ ShortEnumField("type", 5, ofp_action_types),
+                    ShortField("len", 16),
+                    MACField("dl_addr", "0"),
+                    XBitField("pad", 0, 48) ]
+
+class OFPATSetNwSrc(_ofp_action_header):
+    name = "OFPAT_SET_NW_SRC"
+    fields_desc = [ ShortEnumField("type", 6, ofp_action_types),
+                    ShortField("len", 8),
+                    IPField("nw_addr", "0") ]
+
+class OFPATSetNwDst(_ofp_action_header):
+    name = "OFPAT_SET_NW_DST"
+    fields_desc = [ ShortEnumField("type", 7, ofp_action_types),
+                    ShortField("len", 8),
+                    IPField("nw_addr", "0") ]
+
+class OFPATSetNwToS(_ofp_action_header):
+    name = "OFPAT_SET_TP_TOS"
+    fields_desc = [ ShortEnumField("type", 8, ofp_action_types),
+                    ShortField("len", 8),
+                    ByteField("nw_tos", 0),
+                    X3BytesField("pad", 0) ]
+
+class OFPATSetTpSrc(_ofp_action_header):
+    name = "OFPAT_SET_TP_SRC"
+    fields_desc = [ ShortEnumField("type", 9, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("tp_port", 0),
+                    XShortField("pad", 0) ]
+
+class OFPATSetTpDst(_ofp_action_header):
+    name = "OFPAT_SET_TP_DST"
+    fields_desc = [ ShortEnumField("type", 10, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("tp_port", 0),
+                    XShortField("pad", 0) ]
+
+class OFPATEnqueue(_ofp_action_header):
+    name = "OFPAT_ENQUEUE"
+    fields_desc = [ ShortEnumField("type", 11, ofp_action_types),
+                    ShortField("len", 16),
+                    ShortEnumField("port", 0, ofp_port_no),
+                    XBitField("pad", 0, 48),
+                    IntField("queue_id", 0) ]
+
+class OFPATVendor(_ofp_action_header):
+    name = "OFPAT_VENDOR"
+    fields_desc = [ ShortEnumField("type", 65535, ofp_action_types),
+                    ShortField("len", 8),
+                    IntField("vendor", 0) ]
+
+ofp_action_cls = {     0: OFPATOutput,
+                       1: OFPATSetVLANVID,
+                       2: OFPATSetVLANPCP,
+                       3: OFPATStripVLAN,
+                       4: OFPATSetDlSrc,
+                       5: OFPATSetDlDst,
+                       6: OFPATSetNwSrc,
+                       7: OFPATSetNwDst,
+                       8: OFPATSetNwToS,
+                       9: OFPATSetTpSrc,
+                      10: OFPATSetTpDst,
+                      11: OFPATEnqueue,
+                   65535: OFPATVendor }
+
+class ActionPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_action_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_action_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = ActionPacketListField._get_action_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+
+####################### Queues ######################
+
+class _ofp_queue_property_header(Packet):
+    name = "Dummy OpenFlow Queue Property Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+ofp_queue_property_types = { 0: "OFPQT_NONE",
+                             1: "OFPQT_MIN_RATE" }
+
+class OFPQTNone(_ofp_queue_property_header):
+    name = "OFPQT_NONE"
+    fields_desc = [ ShortEnumField("type", 0, ofp_queue_property_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPQTMinRate(_ofp_queue_property_header):
+    name = "OFPQT_MIN_RATE"
+    fields_desc = [ ShortEnumField("type", 1, ofp_queue_property_types),
+                    ShortField("len", 16),
+                    XIntField("pad", 0),
+                    ShortField("rate", 0),
+                    XBitField("pad2", 0, 48) ]
+
+ofp_queue_property_cls = { 0: OFPQTNone,
+                           1: OFPQTMinRate }
+
+class QueuePropertyPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_queue_property_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_queue_property_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        l = 0
+        ret = ""
+        remain = s
+
+        while remain:
+            l = QueuePropertyPacketListField._get_queue_property_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain + ret, lst
+
+class OFPPacketQueue(Packet):
+
+    def extract_padding(self, s):
+        return "", s
+
+    def post_build(self, p, pay):
+        if self.properties == []:
+            p += str(OFPQTNone())
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:4] + struct.pack("!H", l) + p[6:]
+        return p + pay
+
+    name = "OFP_PACKET_QUEUE"
+    fields_desc = [ IntField("queue_id", 0),
+                    ShortField("len", None),
+                    XShortField("pad", 0),
+                    QueuePropertyPacketListField("properties", [], Packet,
+                                                 length_from=lambda pkt:pkt.len-8) ]
+
+class QueuePacketListField(PacketListField):
+
+    @staticmethod
+    def _get_queue_length(s):
+        return struct.unpack("!H", s[4:6])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        l = 0
+        ret = ""
+        remain = s
+
+        while remain:
+            l = QueuePacketListField._get_queue_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPPacketQueue(current)
+            lst.append(p)
+
+        return remain + ret, lst
+
+
+#####################################################
+############## OpenFlow 1.0 Messages ################
+#####################################################
+
+class _ofp_header(Packet):
+    name = "Dummy OpenFlow Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+ofp_version = { 0x01: "OpenFlow 1.0",
+                0x02: "OpenFlow 1.1",
+                0x03: "OpenFlow 1.2",
+                0x04: "OpenFlow 1.3",
+                0x05: "OpenFlow 1.4" }
+
+ofp_type = {  0: "OFPT_HELLO",
+              1: "OFPT_ERROR",
+              2: "OFPT_ECHO_REQUEST",
+              3: "OFPT_ECHO_REPLY",
+              4: "OFPT_VENDOR",
+              5: "OFPT_FEATURES_REQUEST",
+              6: "OFPT_FEATURES_REPLY",
+              7: "OFPT_GET_CONFIG_REQUEST",
+              8: "OFPT_GET_CONFIG_REPLY",
+              9: "OFPT_SET_CONFIG",
+             10: "OFPT_PACKET_IN",
+             11: "OFPT_FLOW_REMOVED",
+             12: "OFPT_PORT_STATUS",
+             13: "OFPT_PACKET_OUT",
+             14: "OFPT_FLOW_MOD",
+             15: "OFPT_PORT_MOD",
+             16: "OFPT_STATS_REQUEST",
+             17: "OFPT_STATS_REPLY",
+             18: "OFPT_BARRIER_REQUEST",
+             19: "OFPT_BARRIER_REPLY",
+             20: "OFPT_QUEUE_GET_CONFIG_REQUEST",
+             21: "OFPT_QUEUE_GET_CONFIG_REPLY" }
+
+class OFPTHello(_ofp_header):
+    name = "OFPT_HELLO"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 0, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+#####################################################
+#################### OFPT_ERROR #####################
+#####################################################
+
+### this class will be used to display some messages
+### sent back by the switch after an error
+class OFPacketField(PacketField):
+    def getfield(self, pkt, s):
+        try:
+            l = s[2:4]
+            l = struct.unpack("!H", l)[0]
+            ofload = s[:l]
+            remain = s[l:]
+            return remain, OpenFlow(None, ofload)(ofload)
+        except:
+            return "", Raw(s)
+
+ofp_error_type = { 0: "OFPET_HELLO_FAILED",
+                   1: "OFPET_BAD_REQUEST",
+                   2: "OFPET_BAD_ACTION",
+                   3: "OFPET_FLOW_MOD_FAILED",
+                   4: "OFPET_PORT_MOD_FAILED",
+                   5: "OFPET_QUEUE_OP_FAILED" }
+
+class OFPETHelloFailed(_ofp_header):
+    name = "OFPET_HELLO_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 0, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPHFC_INCOMPATIBLE",
+                                                   1: "OFPHFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETBadRequest(_ofp_header):
+    name = "OFPET_BAD_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 1, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPBRC_BAD_VERSION",
+                                                   1: "OFPBRC_BAD_TYPE",
+                                                   2: "OFPBRC_BAD_STAT",
+                                                   3: "OFPBRC_BAD_VENDOR",
+                                                   4: "OFPBRC_BAD_SUBTYPE",
+                                                   5: "OFPBRC_EPERM",
+                                                   6: "OFPBRC_BAD_LEN",
+                                                   7: "OFPBRC_BUFFER_EMPTY",
+                                                   8: "OFPBRC_BUFFER_UNKNOWN" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETBadAction(_ofp_header):
+    name = "OFPET_BAD_ACTION"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 2, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPBAC_BAD_TYPE",
+                                                   1: "OFPBAC_BAD_LEN",
+                                                   2: "OFPBAC_BAD_VENDOR",
+                                                   3: "OFPBAC_BAD_VENDOR_TYPE",
+                                                   4: "OFPBAC_BAD_OUT_PORT",
+                                                   5: "OFPBAC_BAD_ARGUMENT",
+                                                   6: "OFPBAC_EPERM",
+                                                   7: "OFPBAC_TOO_MANY",
+                                                   8: "OFPBAC_BAD_QUEUE" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETFlowModFailed(_ofp_header):
+    name = "OFPET_FLOW_MOD_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 3, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPFMFC_ALL_TABLES_FULL",
+                                                   1: "OFPFMFC_OVERLAP",
+                                                   2: "OFPFMFC_EPERM",
+                                                   3: "OFPFMFC_BAD_EMERG_TIMEOUT",
+                                                   4: "OFPFMFC_BAD_COMMAND",
+                                                   5: "OFPFMFC_UNSUPPORTED" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETPortModFailed(_ofp_header):
+    name = "OFPET_PORT_MOD_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 4, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPPMFC_BAD_PORT",
+                                                   1: "OFPPMFC_BAD_HW_ADDR" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETQueueOpFailed(_ofp_header):
+    name = "OFPET_QUEUE_OP_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 5, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPQOFC_BAD_PORT",
+                                                   1: "OFPQOFC_BAD_QUEUE",
+                                                   2: "OFPQOFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+# ofp_error_cls allows generic method OpenFlow() to choose the right class for dissection
+ofp_error_cls = { 0: OFPETHelloFailed,
+                  1: OFPETBadRequest,
+                  2: OFPETBadAction,
+                  3: OFPETFlowModFailed,
+                  4: OFPETPortModFailed,
+                  5: OFPETQueueOpFailed }
+
+################ end of OFPT_ERRORS #################
+
+class OFPTEchoRequest(_ofp_header):
+    name = "OFPT_ECHO_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 2, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTEchoReply(_ofp_header):
+    name = "OFPT_ECHO_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 3, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTVendor(_ofp_header):
+    name = "OFPT_VENDOR"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 4, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntField("vendor", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTFeaturesRequest(_ofp_header):
+    name = "OFPT_FEATURES_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 5, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+ofp_action_types_flags = ofp_action_types.values()[:-1]  # no ofpat_vendor flag
+
+class OFPTFeaturesReply(_ofp_header):
+    name = "OFPT_FEATURES_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 6, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    LongField("datapath_id", 0),
+                    IntField("n_buffers", 0),
+                    ByteField("n_tables", 1),
+                    X3BytesField("pad", 0),
+                    FlagsField("capabilities", 0, 32, [ "FLOW_STATS",
+                                                        "TABLE_STATS",
+                                                        "PORT_STATS",
+                                                        "STP",
+                                                        "RESERVED",
+                                                        "IP_REASM",
+                                                        "QUEUE_STATS",
+                                                        "ARP_MATCH_IP" ]),
+                    FlagsField("actions", 0, 32, ofp_action_types_flags),
+                    PacketListField("ports", None, OFPPhyPort,
+                                    length_from=lambda pkt:pkt.len-32) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTGetConfigRequest(_ofp_header):
+    name = "OFPT_GET_CONFIG_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 7, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTGetConfigReply(_ofp_header):
+    name = "OFPT_GET_CONFIG_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 8, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("flags", 0, { 0: "FRAG_NORMAL",
+                                                 1: "FRAG_DROP",
+                                                 2: "FRAG_REASM",
+                                                 3: "FRAG_MASK" }),
+                    ShortField("miss_send_len", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTSetConfig(_ofp_header):
+    name = "OFPT_SET_CONFIG"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 9, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("flags", 0, { 0: "FRAG_NORMAL",
+                                                 1: "FRAG_DROP",
+                                                 2: "FRAG_REASM",
+                                                 3: "FRAG_MASK" }),
+                    ShortField("miss_send_len", 128) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTPacketIn(_ofp_header):
+    name = "OFPT_PACKET_IN"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 10, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
+                    ShortField("total_len", 0),
+                    ShortEnumField("in_port", 0, ofp_port_no),
+                    ByteEnumField("reason", 0, { 0: "OFPR_NO_MATCH",
+                                                 1: "OFPR_ACTION" }),
+                    XByteField("pad", 0),
+                    PacketField("data", None, Ether) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTFlowRemoved(_ofp_header):
+    name = "OFPT_FLOW_REMOVED"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 11, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    PacketField("match", OFPMatch(), OFPMatch),
+                    LongField("cookie", 0),
+                    ShortField("priority", 0),
+                    ByteEnumField("reason", 0, { 0: "OFPRR_IDLE_TIMEOUT",
+                                                 1: "OFPRR_HARD_TIMEOUT",
+                                                 2: "OFPRR_DELETE" }),
+                    XByteField("pad1", 0),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0),
+                    ShortField("idle_timeout", 0),
+                    XShortField("pad2", 0),
+                    LongField("packet_count", 0),
+                    LongField("byte_count", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTPortStatus(_ofp_header):
+    name = "OFPT_PORT_STATUS"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 12, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ByteEnumField("reason", 0, { 0: "OFPPR_ADD",
+                                                 1: "OFPPR_DELETE",
+                                                 2: "OFPPR_MODIFY" }),
+                    XBitField("pad", 0, 56),
+                    PacketField("desc", OFPPhyPort(), OFPPhyPort) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTPacketOut(_ofp_header):
+    name = "OFPT_PACKET_OUT"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 13, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
+                    ShortEnumField("in_port", "NONE", ofp_port_no),
+                    FieldLenField("actions_len", None, fmt="H", length_of="actions"),
+                    ActionPacketListField("actions", [], Packet,
+                                          length_from=lambda pkt:pkt.actions_len),
+                    PacketField("data", None, Ether) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTFlowMod(_ofp_header):
+    name = "OFPT_FLOW_MOD"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 14, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    PacketField("match", OFPMatch(), OFPMatch),
+                    LongField("cookie", 0),
+                    ShortEnumField("cmd", 0, { 0: "OFPFC_ADD",
+                                               1: "OFPFC_MODIFY",
+                                               2: "OFPFC_MODIFY_STRICT",
+                                               3: "OFPFC_DELETE",
+                                               4: "OFPFC_DELETE_STRICT" }),
+                    ShortField("idle_timeout", 0),
+                    ShortField("hard_timeout", 0),
+                    ShortField("priority", 0),
+                    IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
+                    ShortEnumField("out_port", "NONE", ofp_port_no),
+                    FlagsField("flags", 0, 16, [ "SEND_FLOW_REM",
+                                                 "CHECK_OVERLAP",
+                                                 "EMERG" ]),
+                    ActionPacketListField("actions", [], Packet,
+                                          length_from=lambda pkt:pkt.len-72) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTPortMod(_ofp_header):
+    name = "OFPT_PORT_MOD"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 15, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("port_no", 0, ofp_port_no),
+                    MACField("hw_addr", "0"),
+                    FlagsField("config", 0, 32, ofp_port_config),
+                    FlagsField("mask", 0, 32, ofp_port_config),
+                    FlagsField("advertise", 0, 32, ofp_port_features),
+                    IntField("pad", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+#####################################################
+##################### OFPT_STATS ####################
+#####################################################
+
+ofp_stats_types = {     0: "OFPST_DESC",
+                        1: "OFPST_FLOW",
+                        2: "OFPST_AGGREGATE",
+                        3: "OFPST_TABLE",
+                        4: "OFPST_PORT",
+                        5: "OFPST_QUEUE",
+                    65535: "OFPST_VENDOR" }
+
+class OFPTStatsRequestDesc(_ofp_header):
+    name = "OFPST_STATS_REQUEST_DESC"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 0, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTStatsReplyDesc(_ofp_header):
+    name = "OFPST_STATS_REPLY_DESC"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 0, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    StrFixedLenField("mfr_desc", "", 256),
+                    StrFixedLenField("hw_desc", "", 256),
+                    StrFixedLenField("sw_desc", "", 256),
+                    StrFixedLenField("serial_num", "", 32),
+                    StrFixedLenField("dp_desc", "", 256) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTStatsRequestFlow(_ofp_header):
+    name = "OFPST_STATS_REQUEST_FLOW"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 1, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    PacketField("match", OFPMatch(), OFPMatch),
+                    ByteEnumField("table_id", "ALL", ofp_table),
+                    ByteField("pad", 0),
+                    ShortEnumField("out_port", "NONE", ofp_port_no) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPFlowStats(Packet):
+
+    def post_build(self, p, pay):
+        if self.length is None:
+            l = len(p)+len(pay)
+            p = struct.pack("!H", l) + p[2:]
+        return p + pay
+
+    name = "OFP_FLOW_STATS"
+    fields_desc = [ ShortField("length", None),
+                    ByteField("table_id", 0),
+                    XByteField("pad1", 0),
+                    PacketField("match", OFPMatch(), OFPMatch),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0),
+                    ShortField("priority", 0),
+                    ShortField("idle_timeout", 0),
+                    ShortField("hard_timeout", 0),
+                    XBitField("pad2", 0, 48),
+                    LongField("cookie", 0),
+                    LongField("packet_count", 0),
+                    LongField("byte_count", 0),
+                    ActionPacketListField("actions", [], Packet,
+                                          length_from=lambda pkt:pkt.length-88) ]
+
+class FlowStatsPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_flow_stats_length(s):
+        return struct.unpack("!H", s[:2])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = FlowStatsPacketListField._get_flow_stats_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPFlowStats(current)
+            lst.append(p)
+
+        return remain, lst
+
+class OFPTStatsReplyFlow(_ofp_header):
+    name = "OFPST_STATS_REPLY_FLOW"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 1, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    FlowStatsPacketListField("flow_stats", [], Packet,
+                                             length_from=lambda pkt:pkt.len-12) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTStatsRequestAggregate(_ofp_header):
+    name = "OFPST_STATS_REQUEST_AGGREGATE"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 2, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    PacketField("match", OFPMatch(), OFPMatch),
+                    ByteEnumField("table_id", "ALL", ofp_table),
+                    ByteField("pad", 0),
+                    ShortEnumField("out_port", "NONE", ofp_port_no) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTStatsReplyAggregate(_ofp_header):
+    name = "OFPST_STATS_REPLY_AGGREGATE"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 2, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    LongField("packet_count", 0),
+                    LongField("byte_count", 0),
+                    IntField("flow_count", 0),
+                    XIntField("pad", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTStatsRequestTable(_ofp_header):
+    name = "OFPST_STATS_REQUEST_TABLE"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 3, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTableStats(Packet):
+
+    def extract_padding(self, s):
+        return "", s
+
+    name = "OFP_TABLE_STATS"
+    fields_desc = [ ByteField("table_id", 0),
+                    X3BytesField("pad", 0),
+                    StrFixedLenField("name", "", 32),
+                    FlagsField("wildcards1", 0x003, 12, [ "DL_VLAN_PCP",
+                                                          "NW_TOS" ]),
+                    BitField("nw_dst_mask", 63, 6),        # 32 would be enough
+                    BitField("nw_src_mask", 63, 6),
+                    FlagsField("wildcards2", 0xff, 8, [ "IN_PORT",
+                                                        "DL_VLAN",
+                                                        "DL_SRC",
+                                                        "DL_DST",
+                                                        "DL_TYPE",
+                                                        "NW_PROTO",
+                                                        "TP_SRC",
+                                                        "TP_DST" ]),
+                    IntField("max_entries", 0),
+                    IntField("active_count", 0),
+                    LongField("lookup_count", 0),
+                    LongField("matched_count", 0) ]
+
+class OFPTStatsReplyTable(_ofp_header):
+    name = "OFPST_STATS_REPLY_TABLE"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 3, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    PacketListField("table_stats", None, OFPTableStats,
+                                    length_from=lambda pkt:pkt.len-12) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTStatsRequestPort(_ofp_header):
+    name = "OFPST_STATS_REQUEST_PORT"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 4, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    ShortEnumField("port_no", "NONE", ofp_port_no),
+                    XBitField("pad", 0, 48) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPPortStats(Packet):
+
+    def extract_padding(self, s):
+        return "", s
+
+    name = "OFP_PORT_STATS"
+    fields_desc = [ ShortEnumField("port_no", 0, ofp_port_no),
+                    XBitField("pad", 0, 48),
+                    LongField("rx_packets", 0),
+                    LongField("tx_packets", 0),
+                    LongField("rx_bytes", 0),
+                    LongField("tx_bytes", 0),
+                    LongField("rx_dropped", 0),
+                    LongField("tx_dropped", 0),
+                    LongField("rx_errors", 0),
+                    LongField("tx_errors", 0),
+                    LongField("rx_frame_err", 0),
+                    LongField("rx_over_err", 0),
+                    LongField("rx_crc_err", 0),
+                    LongField("collisions", 0) ]
+
+class OFPTStatsReplyPort(_ofp_header):
+    name = "OFPST_STATS_REPLY_TABLE"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 4, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    PacketListField("port_stats", None, OFPPortStats,
+                                    length_from=lambda pkt:pkt.len-12) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTStatsRequestQueue(_ofp_header):
+    name = "OFPST_STATS_REQUEST_QUEUE"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 5, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    ShortEnumField("port_no", "NONE", ofp_port_no),
+                    XShortField("pad", 0),
+                    IntEnumField("queue_id", "ALL", ofp_queue) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTStatsReplyQueue(_ofp_header):
+    name = "OFPST_STATS_REPLY_QUEUE"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 5, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    ShortEnumField("port_no", "NONE", ofp_port_no),
+                    XShortField("pad", 0),
+                    IntEnumField("queue_id", "ALL", ofp_queue),
+                    LongField("tx_bytes", 0),
+                    LongField("tx_packets", 0),
+                    LongField("tx_errors", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTStatsRequestVendor(_ofp_header):
+    name = "OFPST_STATS_REQUEST_VENDOR"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 6, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    IntField("vendor", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTStatsReplyVendor(_ofp_header):
+    name = "OFPST_STATS_REPLY_VENDOR"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("stats_type", 6, ofp_stats_types),
+                    FlagsField("flags", 0, 16, []),
+                    IntField("vendor", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+# ofp_stats_request/reply_cls allows generic method OpenFlow() (end of script)
+# to choose the right class for dissection
+ofp_stats_request_cls = {     0: OFPTStatsRequestDesc,
+                              1: OFPTStatsRequestFlow,
+                              2: OFPTStatsRequestAggregate,
+                              3: OFPTStatsRequestTable,
+                              4: OFPTStatsRequestPort,
+                              5: OFPTStatsRequestQueue,
+                          65535: OFPTStatsRequestVendor }
+
+ofp_stats_reply_cls = {     0: OFPTStatsReplyDesc,
+                            1: OFPTStatsReplyFlow,
+                            2: OFPTStatsReplyAggregate,
+                            3: OFPTStatsReplyTable,
+                            4: OFPTStatsReplyPort,
+                            5: OFPTStatsReplyQueue,
+                        65535: OFPTStatsReplyVendor }
+
+################ end of OFPT_STATS ##################
+
+class OFPTBarrierRequest(_ofp_header):
+    name = "OFPT_BARRIER_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTBarrierReply(_ofp_header):
+    name = "OFPT_BARRIER_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTQueueGetConfigRequest(_ofp_header):
+    name = "OFPT_QUEUE_GET_CONFIG_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 20, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("port", 0, ofp_port_no),
+                    XShortField("pad", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTQueueGetConfigReply(_ofp_header):
+    name = "OFPT_QUEUE_GET_CONFIG_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x01, ofp_version),
+                    ByteEnumField("type", 21, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("port", 0, ofp_port_no),
+                    XBitField("pad", 0, 48),
+                    QueuePacketListField("queues", [], Packet,
+                                         length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+# ofpt_cls allows generic method OpenFlow() to choose the right class for dissection
+ofpt_cls = {  0: OFPTHello,
+              #1: OFPTError,
+              2: OFPTEchoRequest,
+              3: OFPTEchoReply,
+              4: OFPTVendor,
+              5: OFPTFeaturesRequest,
+              6: OFPTFeaturesReply,
+              7: OFPTGetConfigRequest,
+              8: OFPTGetConfigReply,
+              9: OFPTSetConfig,
+             10: OFPTPacketIn,
+             11: OFPTFlowRemoved,
+             12: OFPTPortStatus,
+             13: OFPTPacketOut,
+             14: OFPTFlowMod,
+             15: OFPTPortMod,
+             #16: OFPTStatsRequest,
+             #17: OFPTStatsReply,
+             18: OFPTBarrierRequest,
+             19: OFPTBarrierReply,
+             20: OFPTQueueGetConfigRequest,
+             21: OFPTQueueGetConfigReply }
+
+TCP_guess_payload_class_copy = TCP.guess_payload_class
+
+def OpenFlow(self, payload):
+    if self is None or self.dport == 6653 or self.dport == 6633 or self.sport == 6653 or self.sport == 6653:
+    # port 6653 has been allocated by IANA, port 6633 should no longer be used
+    # OpenFlow function may be called with None self in OFPPacketField
+        of_type = ord(payload[1])
+        if of_type == 1:
+            err_type = ord(payload[9])
+            # err_type is a short int, but last byte is enough
+            if err_type == 255: err_type = 65535
+            return ofp_error_cls[err_type]
+        elif of_type == 16:
+            mp_type = ord(payload[9])
+            if mp_type == 255: mp_type = 65535
+            return ofp_stats_request_cls[mp_type]
+        elif of_type == 17:
+            mp_type = ord(payload[9])
+            if mp_type == 255: mp_type = 65535
+            return ofp_stats_reply_cls[mp_type]
+        else:
+            return ofpt_cls[of_type]
+    else:
+        return TCP_guess_payload_class_copy(self, payload)
+
+TCP.guess_payload_class = OpenFlow
diff --git a/scapy/contrib/openflow.uts b/scapy/contrib/openflow.uts
new file mode 100755
index 0000000000000000000000000000000000000000..a26af678b819990044b337f2703995ea4db60384
--- /dev/null
+++ b/scapy/contrib/openflow.uts
@@ -0,0 +1,81 @@
+% Tests for OpenFlow v1.0 with Scapy
+
++ Usual OFv1.0 messages
+
+= OFPTHello(), simple hello message
+ofm = OFPTHello()
+str(ofm) == '\x01\x00\x00\x08\x00\x00\x00\x00'
+
+= OFPTEchoRequest(), echo request
+ofm = OFPTEchoRequest()
+str(ofm) == '\x01\x02\x00\x08\x00\x00\x00\x00'
+
+= OFPMatch(), check wildcard completion
+ofm = OFPMatch(in_port=1, nw_tos=8)
+ofm = OFPMatch(str(ofm))
+assert(ofm.wildcards1 == 0x1)
+ofm.wildcards2 == 0xfe
+
+= OpenFlow(), generic method test with OFPTEchoRequest()
+ofm = OFPTEchoRequest()
+s = str(ofm)
+isinstance(OpenFlow(None,s)(s), OFPTEchoRequest)
+
+= OFPTFlowMod(), check codes and defaults values
+ofm = OFPTFlowMod(cmd='OFPFC_DELETE', out_port='CONTROLLER', flags='CHECK_OVERLAP+EMERG')
+assert(ofm.cmd == 3)
+assert(ofm.buffer_id == 0xffffffff)
+assert(ofm.out_port == 0xfffd)
+ofm.flags == 6
+
++ Complex OFv1.3 messages
+
+= OFPTFlowMod(), complex flow_mod
+mtc = OFPMatch(dl_vlan=10, nw_src='192.168.42.0', nw_src_mask=8)
+act1 = OFPATSetNwSrc(nw_addr='192.168.42.1')
+act2 = OFPATOutput(port='CONTROLLER')
+act3 = OFPATSetDlSrc(dl_addr='1a:d5:cb:4e:3c:64')
+ofm = OFPTFlowMod(priority=1000, match=mtc, flags='CHECK_OVERLAP', actions=[act1,act2,act3])
+str(ofm)
+s = '\x01\x0e\x00h\x00\x00\x00\x00\x00?\xc8\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8*\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xe8\xff\xff\xff\xff\xff\xff\x00\x02\x00\x06\x00\x08\xc0\xa8*\x01\x00\x00\x00\x08\xff\xfd\xff\xff\x00\x04\x00\x10\x1a\xd5\xcbN<d\x00\x00\x00\x00\x00\x00'
+str(ofm) == s
+
+= OFPETBadRequest() containing a flow_mod with wrong table_id
+flowmod = OFPTFlowMod(actions=OFPATOutput(port='LOCAL'))
+ofm = OFPETBadRequest(errcode='OFPBRC_EPERM', data=str(flowmod))
+hexdump(ofm)
+s = '\x01\x01\x00\\\x00\x00\x00\x00\x00\x01\x00\x05\x01\x0e\x00P\x00\x00\x00\x00\x00?\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x08\xff\xfe\xff\xff'
+str(ofm) == s
+
+= OFPTPacketIn() containing an Ethernet frame
+ofm = OFPTPacketIn(data=Ether()/IP()/ICMP())
+p = OFPTPacketIn(str(ofm))
+dat = p.data
+assert(isinstance(dat, Ether))
+assert(isinstance(dat.payload, IP))
+isinstance(dat.payload.payload, ICMP)
+
++ Layer bindings
+
+= TCP()/OFPTStatsRequestDesc(), check default sport
+p = TCP()/OFPTStatsRequestDesc()
+p[TCP].sport == 6653
+
+= TCP()/OFPETHelloFailed(), check default dport
+p = TCP()/OFPETHelloFailed()
+p[TCP].dport == 6653
+
+= TCP()/OFPTHello() dissection, check new TCP.guess_payload_class
+o = TCP()/OFPTHello()
+p = TCP(str(o))
+p[TCP].sport == 6653
+isinstance(p[TCP].payload, OFPTHello)
+
+= complete Ether()/IP()/TCP()/OFPTFeaturesRequest()
+ofm = Ether(src='00:11:22:33:44:55',dst='01:23:45:67:89:ab')/IP(src='10.0.0.7',dst='192.168.0.42')/TCP(sport=6633)/OFPTFeaturesRequest(xid=23)
+s = '\x01#Eg\x89\xab\x00\x11"3DU\x08\x00E\x00\x000\x00\x01\x00\x00@\x06\xaf\xee\n\x00\x00\x07\xc0\xa8\x00*\x19\xe9\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\xa9\xa4\x00\x00\x01\x05\x00\x08\x00\x00\x00\x17'
+assert(str(ofm) == s)
+e = Ether(s)
+e.show2()
+of = OFPTFeaturesRequest(e[TCP].load)
+of.xid == 23
diff --git a/scapy/contrib/openflow3.py b/scapy/contrib/openflow3.py
new file mode 100755
index 0000000000000000000000000000000000000000..64828722fa890b7beda48287604d49bbde029605
--- /dev/null
+++ b/scapy/contrib/openflow3.py
@@ -0,0 +1,3369 @@
+## This file is part of Scapy
+## See http://www.secdev.org/projects/scapy for more information
+## Copyright (C) Philippe Biondi <phil@secdev.org>
+## This program is published under a GPLv2 license
+
+## Copyright (C) 2014 Maxence Tury <maxence.tury@ssi.gouv.fr>
+## OpenFlow is an open standard used in SDN deployments.
+## Based on OpenFlow v1.3.4
+## Specifications can be retrieved from https://www.opennetworking.org/
+
+# scapy.contrib.description = openflow v1.3
+# scapy.contrib.status = loads
+
+import struct
+from scapy.all import *
+
+### If prereq_autocomplete is True then match prerequisites will be
+### automatically handled. See OFPMatch class.
+prereq_autocomplete = False
+
+#####################################################
+################# Predefined values #################
+#####################################################
+
+ofp_port_no = { 0xfffffff8: "IN_PORT",
+                0xfffffff9: "TABLE",
+                0xfffffffa: "NORMAL",
+                0xfffffffb: "FLOOD",
+                0xfffffffc: "ALL",
+                0xfffffffd: "CONTROLLER",
+                0xfffffffe: "LOCAL",
+                0xffffffff: "ANY" }
+
+ofp_group = { 0xffffff00: "MAX",
+              0xfffffffc: "ALL",
+              0xffffffff: "ANY" }
+
+ofp_table = { 0xfe: "MAX",
+              0xff: "ALL" }
+
+ofp_queue = { 0xffffffff: "ALL" }
+
+ofp_meter = { 0xffff0000: "MAX",
+              0xfffffffd: "SLOWPATH",
+              0xfffffffe: "CONTROLLER",
+              0xffffffff: "ALL" }
+
+ofp_buffer = { 0xffffffff: "NO_BUFFER" }
+
+ofp_max_len = { 0xffff: "NO_BUFFER" }
+
+
+#####################################################
+################# Common structures #################
+#####################################################
+
+### The following structures will be used in different types
+### of OpenFlow messages: ports, matches/OXMs, actions,
+### instructions, buckets, queues, meter bands.
+
+
+################## Hello elements ###################
+
+class _ofp_hello_elem_header(Packet):
+    name = "Dummy OpenFlow Hello Elem Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+ofp_hello_elem_types = { 1: "OFPHET_VERSIONBITMAP" }
+
+class OFPHETVersionBitmap(_ofp_hello_elem_header):
+    name = "OFPHET_VERSIONBITMAP"
+    fields_desc = [ ShortEnumField("type", 1, ofp_hello_elem_types),
+                    ShortField("len", 8),
+                    FlagsField("bitmap", 0, 32, [ "Type 0",
+                                                  "OFv1.0",
+                                                  "OFv1.1",
+                                                  "OFv1.2",
+                                                  "OFv1.3",
+                                                  "OFv1.4" ]) ]
+
+ofp_hello_elem_cls = { 1: OFPHETVersionBitmap }
+
+class HelloElemPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_hello_elem_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_hello_elem_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = HelloElemPacketListField._get_hello_elem_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+
+####################### Ports #######################
+
+ofp_port_config = [ "PORT_DOWN",
+                    "NO_STP",        # undefined in v1.3
+                    "NO_RECV",
+                    "NO_RECV_STP",   # undefined in v1.3
+                    "NO_FLOOD",      # undefined in v1.3
+                    "NO_FWD",
+                    "NO_PACKET_IN" ]
+
+ofp_port_state = [ "LINK_DOWN",
+                   "BLOCKED",
+                   "LIVE" ]
+
+ofp_port_features = [ "10MB_HD",
+                      "10MB_FD",
+                      "100MB_HD",
+                      "100MB_FD",
+                      "1GB_HD",
+                      "1GB_FD",
+                      "10GB_FD",
+                      "40GB_FD",
+                      "100GB_FD",
+                      "1TB_FD",
+                      "OTHER",
+                      "COPPER",
+                      "FIBER",
+                      "AUTONEG",
+                      "PAUSE",
+                      "PAUSE_ASYM" ]
+
+class OFPPort(Packet):
+    name = "OFP_PHY_PORT"
+    fields_desc = [ IntEnumField("port_no", 0, ofp_port_no),
+                    XIntField("pad1", 0),
+                    MACField("hw_addr", "0"),
+                    XShortField("pad2", 0),
+                    StrFixedLenField("port_name", "", 16),
+                    FlagsField("config", 0, 32, ofp_port_config),
+                    FlagsField("state", 0, 32, ofp_port_state),
+                    FlagsField("curr", 0, 32, ofp_port_features),
+                    FlagsField("advertised", 0, 32, ofp_port_features),
+                    FlagsField("supported", 0, 32, ofp_port_features),
+                    FlagsField("peer", 0, 32, ofp_port_features),
+                    IntField("curr_speed", 0),
+                    IntField("max_speed", 0) ]
+
+    def extract_padding(self, s):
+        return "", s
+    # extract_padding is overridden in order for s not to be considered
+    # as belonging to the same layer (s usually contains other OFPPorts)
+
+
+################### Matches & OXMs ##################
+
+ofp_oxm_classes = {      0: "OFPXMC_NXM_0",
+                         1: "OFPXMC_NXM_1",
+                    0x8000: "OFPXMC_OPENFLOW_BASIC",
+                    0xffff: "OFPXMC_EXPERIMENTER" }
+
+ofp_oxm_names = {  0: "OFB_IN_PORT",
+                   1: "OFB_IN_PHY_PORT",
+                   2: "OFB_METADATA",
+                   3: "OFB_ETH_DST",
+                   4: "OFB_ETH_SRC",
+                   5: "OFB_ETH_TYPE",
+                   6: "OFB_VLAN_VID",
+                   7: "OFB_VLAN_PCP",
+                   8: "OFB_IP_DSCP",
+                   9: "OFB_IP_ECN",
+                  10: "OFB_IP_PROTO",
+                  11: "OFB_IPV4_SRC",
+                  12: "OFB_IPV4_DST",
+                  13: "OFB_TCP_SRC",
+                  14: "OFB_TCP_DST",
+                  15: "OFB_UDP_SRC",
+                  16: "OFB_UDP_DST",
+                  17: "OFB_SCTP_SRC",
+                  18: "OFB_SCTP_DST",
+                  19: "OFB_ICMPV4_TYPE",
+                  20: "OFB_ICMPV4_CODE",
+                  21: "OFB_ARP_OP",
+                  22: "OFB_ARP_SPA",
+                  23: "OFB_ARP_TPA",
+                  24: "OFB_ARP_SHA",
+                  25: "OFB_ARP_THA",
+                  26: "OFB_IPV6_SRC",
+                  27: "OFB_IPV6_DST",
+                  28: "OFB_IPV6_FLABEL",
+                  29: "OFB_ICMPV6_TYPE",
+                  30: "OFB_ICMPV6_CODE",
+                  31: "OFB_IPV6_ND_TARGET",
+                  32: "OFB_IPV6_ND_SLL",
+                  33: "OFB_IPV6_ND_TLL",
+                  34: "OFB_MPLS_LABEL",
+                  35: "OFB_MPLS_TC",
+                  36: "OFB_MPLS_BOS",
+                  37: "OFB_PBB_ISID",
+                  38: "OFB_TUNNEL_ID",
+                  39: "OFB_IPV6_EXTHDR" }
+
+ofp_oxm_constr = {  0: ["OFBInPort", "in_port", 4],
+                    1: ["OFBInPhyPort", "in_phy_port", 4],
+                    2: ["OFBMetadata", "metadata", 8],
+                    3: ["OFBEthDst", "eth_dst", 6],
+                    4: ["OFBEthSrc", "eth_src", 6],
+                    5: ["OFBEthType", "eth_type", 2],
+                    6: ["OFBVLANVID", "vlan_vid", 2],
+                    7: ["OFBVLANPCP", "vlan_pcp", 1],
+                    8: ["OFBIPDSCP", "ip_dscp", 1],
+                    9: ["OFBIPECN", "ip_ecn", 1],
+                   10: ["OFBIPProto", "ip_proto", 1],
+                   11: ["OFBIPv4Src", "ipv4_src", 4],
+                   12: ["OFBIPv4Dst", "ipv4_dst", 4],
+                   13: ["OFBTCPSrc", "tcp_src", 2],
+                   14: ["OFBTCPDst", "tcp_dst", 2],
+                   15: ["OFBUDPSrc", "udp_src", 2],
+                   16: ["OFBUDPDst", "udp_dst", 2],
+                   17: ["OFBSCTPSrc", "sctp_src", 2],
+                   18: ["OFBSCTPDst", "sctp_dst", 2],
+                   19: ["OFBICMPv4Type", "icmpv4_type", 1],    
+                   20: ["OFBICMPv4Code", "icmpv4_code", 1],    
+                   21: ["OFBARPOP", "arp_op", 2],    
+                   22: ["OFBARPSPA", "arp_spa", 4],
+                   23: ["OFBARPTPA", "arp_tpa", 4],
+                   24: ["OFBARPSHA", "arp_sha", 6],
+                   25: ["OFBARPTHA", "arp_tha", 6],
+                   26: ["OFBIPv6Src", "ipv6_src", 16],
+                   27: ["OFBIPv6Dst", "ipv6_dst", 16],
+                   28: ["OFBIPv6FLabel", "ipv6_flabel", 4],
+                   29: ["OFBICMPv6Type", "icmpv6_type", 1],
+                   30: ["OFBICMPv6Code", "icmpv6_code", 1],
+                   31: ["OFBIPv6NDTarget", "ipv6_nd_target", 16],
+                   32: ["OFBIPv6NDSLL", "ipv6_sll", 6],
+                   33: ["OFBIPv6NDTLL", "ipv6_tll", 6],
+                   34: ["OFBMPLSLabel", "mpls_label", 4],
+                   35: ["OFBMPLSTC", "mpls_tc", 1],
+                   36: ["OFBMPLSBoS", "mpls_bos", 1],
+                   37: ["OFBPBBISID", "pbb_isid", 3],
+                   38: ["OFBTunnelID", "tunnel_id", 8],
+                   39: ["OFBIPv6ExtHdr", "ipv6_ext_hdr_flags", 2] }
+
+# the ipv6flags array is useful only to the OFBIPv6ExtHdr class
+ipv6flags = [ "NONEXT",
+              "ESP",
+              "AUTH",
+              "DEST",
+              "FRAG",
+              "ROUTER",
+              "HOP",
+              "UNREP",
+              "UNSEQ" ]
+
+### here we fill ofp_oxm_fields with the fields that will be used
+### to generate the various OXM classes
+### e.g. the call to add_ofp_oxm_fields(0, ["OFBInPort", "in_port", 4])
+### will add {0: [ShortEnumField("class",..), BitEnumField("field",..),..]}
+ofp_oxm_fields = {}
+def add_ofp_oxm_fields(i, org):
+    ofp_oxm_fields[i] = [ ShortEnumField("class", "OFPXMC_OPENFLOW_BASIC", ofp_oxm_classes),
+                          BitEnumField("field", i/2, 7, ofp_oxm_names),
+                          BitField("hasmask", i%2, 1) ]
+    ofp_oxm_fields[i].append(ByteField("length", org[2]+org[2]*(i%2)))
+    if i/2 == 0:           # OFBInPort
+        ofp_oxm_fields[i].append(IntEnumField(org[1], 0, ofp_port_no))
+    elif i/2 == 3 or i/2 == 4:          # OFBEthSrc & OFBEthDst
+        ofp_oxm_fields[i].append(MACField(org[1], None))
+    elif i/2 == 11 or i/2 == 12:        # OFBIPv4Src & OFBIPv4Dst
+        ofp_oxm_fields[i].append(IPField(org[1], "0"))
+    elif i/2 == 39:        # OFBIPv6ExtHdr
+        ofp_oxm_fields[i].append(FlagsField(org[1], 0, 8*org[2], ipv6flags))
+    else:
+        ofp_oxm_fields[i].append(BitField(org[1], 0, 8*org[2]))
+    if i%2:
+        ofp_oxm_fields[i].append(BitField(org[1]+"_mask", 0, 8*org[2]))
+
+# some HM classes are not supported par OFv1.3 but we will create them anyway
+for i,cls in ofp_oxm_constr.items():
+    add_ofp_oxm_fields(2*i, cls)
+    add_ofp_oxm_fields(2*i+1, cls)
+
+### now we create every OXM class with the same call,
+### (except that static variable create_oxm_class.i is each time different)
+### and we fill ofp_oxm_cls with them
+ofp_oxm_cls = {}
+ofp_oxm_id_cls = {}
+def create_oxm_cls():
+    # static variable initialization
+    if not hasattr(create_oxm_cls, "i"):
+        create_oxm_cls.i = 0
+
+    index = create_oxm_cls.i
+    cls_name = ofp_oxm_constr[index/4][0]
+    # we create standard OXM then OXM ID then OXM with mask then OXM-hasmask ID
+    if index % 4 == 2:
+        cls_name += "HM"
+    if index % 2:
+        cls_name += "ID"
+
+    oxm_name = ofp_oxm_names[index/4]
+    oxm_fields = ofp_oxm_fields[index/2]
+    # for ID classes we just want the first 4 fields (no payload)
+    if index % 2:
+        oxm_fields = oxm_fields[:4]
+
+    cls = type(cls_name, (Packet,), { "name": oxm_name, "fields_desc": oxm_fields })
+    ### the first call to special function type will create the same class as in
+    ### class OFBInPort(Packet):
+    ###     def __init__(self):
+    ###         self.name = "OFB_IN_PORT"
+    ###         self.fields_desc = [ ShortEnumField("class", 0x8000, ofp_oxm_classes),
+    ###                              BitEnumField("field", 0, 7, ofp_oxm_names),
+    ###                              BitField("hasmask", 0, 1),
+    ###                              ByteField("length", 4),
+    ###                              IntEnumField("in_port", 0, ofp_port_no) ]
+
+    if index % 2 == 0:
+        ofp_oxm_cls[index/2] = cls
+    else:
+        ofp_oxm_id_cls[index/2] = cls
+    create_oxm_cls.i += 1
+    return cls
+
+OFBInPort = create_oxm_cls()
+OFBInPortID = create_oxm_cls()
+OFBInPortHM = create_oxm_cls()
+OFBInPortHMID = create_oxm_cls()
+OFBInPhyPort = create_oxm_cls()
+OFBInPhyPortID = create_oxm_cls()
+OFBInPhyPortHM = create_oxm_cls()
+OFBInPhyPortHMID = create_oxm_cls()
+OFBMetadata = create_oxm_cls()
+OFBMetadataID = create_oxm_cls()
+OFBMetadataHM = create_oxm_cls()
+OFBMetadataHMID = create_oxm_cls()
+OFBEthDst = create_oxm_cls()
+OFBEthDstID = create_oxm_cls()
+OFBEthDstHM = create_oxm_cls()
+OFBEthDstHMID = create_oxm_cls()
+OFBEthSrc = create_oxm_cls()
+OFBEthSrcID = create_oxm_cls()
+OFBEthSrcHM = create_oxm_cls()
+OFBEthSrcHMID = create_oxm_cls()
+OFBEthType = create_oxm_cls()
+OFBEthTypeID = create_oxm_cls()
+OFBEthTypeHM = create_oxm_cls()
+OFBEthTypeHMID = create_oxm_cls()
+OFBVLANVID = create_oxm_cls()
+OFBVLANVIDID = create_oxm_cls()
+OFBVLANVIDHM = create_oxm_cls()
+OFBVLANVIDHMID = create_oxm_cls()
+OFBVLANPCP = create_oxm_cls()
+OFBVLANPCPID = create_oxm_cls()
+OFBVLANPCPHM = create_oxm_cls()
+OFBVLANPCPHMID = create_oxm_cls()
+OFBIPDSCP = create_oxm_cls()
+OFBIPDSCPID = create_oxm_cls()
+OFBIPDSCPHM = create_oxm_cls()
+OFBIPDSCPHMID = create_oxm_cls()
+OFBIPECN = create_oxm_cls()
+OFBIPECNID = create_oxm_cls()
+OFBIPECNHM = create_oxm_cls()
+OFBIPECNHMID = create_oxm_cls()
+OFBIPProto = create_oxm_cls()
+OFBIPProtoID = create_oxm_cls()
+OFBIPProtoHM = create_oxm_cls()
+OFBIPProtoHMID = create_oxm_cls()
+OFBIPv4Src = create_oxm_cls()
+OFBIPv4SrcID = create_oxm_cls()
+OFBIPv4SrcHM = create_oxm_cls()
+OFBIPv4SrcHMID = create_oxm_cls()
+OFBIPv4Dst = create_oxm_cls()
+OFBIPv4DstID = create_oxm_cls()
+OFBIPv4DstHM = create_oxm_cls()
+OFBIPv4DstHMID = create_oxm_cls()
+OFBTCPSrc = create_oxm_cls()
+OFBTCPSrcID = create_oxm_cls()
+OFBTCPSrcHM = create_oxm_cls()
+OFBTCPSrcHMID = create_oxm_cls()
+OFBTCPDst = create_oxm_cls()
+OFBTCPDstID = create_oxm_cls()
+OFBTCPDstHM = create_oxm_cls()
+OFBTCPDstHMID = create_oxm_cls()
+OFBUDPSrc = create_oxm_cls()
+OFBUDPSrcID = create_oxm_cls()
+OFBUDPSrcHM = create_oxm_cls()
+OFBUDPSrcHMID = create_oxm_cls()
+OFBUDPDst = create_oxm_cls()
+OFBUDPDstID = create_oxm_cls()
+OFBUDPDstHM = create_oxm_cls()
+OFBUDPDstHMID = create_oxm_cls()
+OFBSCTPSrc = create_oxm_cls()
+OFBSCTPSrcID = create_oxm_cls()
+OFBSCTPSrcHM = create_oxm_cls()
+OFBSCTPSrcHMID = create_oxm_cls()
+OFBSCTPDst = create_oxm_cls()
+OFBSCTPDstID = create_oxm_cls()
+OFBSCTPDstHM = create_oxm_cls()
+OFBSCTPDstHMID = create_oxm_cls()
+OFBICMPv4Type = create_oxm_cls()
+OFBICMPv4TypeID = create_oxm_cls()
+OFBICMPv4TypeHM = create_oxm_cls()
+OFBICMPv4TypeHMID = create_oxm_cls()
+OFBICMPv4Code = create_oxm_cls()
+OFBICMPv4CodeID = create_oxm_cls()
+OFBICMPv4CodeHM = create_oxm_cls()
+OFBICMPv4CodeHMID = create_oxm_cls()
+OFBARPOP = create_oxm_cls()
+OFBARPOPID = create_oxm_cls()
+OFBARPOPHM = create_oxm_cls()
+OFBARPOPHMID = create_oxm_cls()
+OFBARPSPA = create_oxm_cls()
+OFBARPSPAID = create_oxm_cls()
+OFBARPSPAHM = create_oxm_cls()
+OFBARPSPAHMID = create_oxm_cls()
+OFBARPTPA = create_oxm_cls()
+OFBARPTPAID = create_oxm_cls()
+OFBARPTPAHM = create_oxm_cls()
+OFBARPTPAHMID = create_oxm_cls()
+OFBARPSHA = create_oxm_cls()
+OFBARPSHAID = create_oxm_cls()
+OFBARPSHAHM = create_oxm_cls()
+OFBARPSHAHMID = create_oxm_cls()
+OFBARPTHA = create_oxm_cls()
+OFBARPTHAID = create_oxm_cls()
+OFBARPTHAHM = create_oxm_cls()
+OFBARPTHAHMID = create_oxm_cls()
+OFBIPv6Src = create_oxm_cls()
+OFBIPv6SrcID = create_oxm_cls()
+OFBIPv6SrcHM = create_oxm_cls()
+OFBIPv6SrcHMID = create_oxm_cls()
+OFBIPv6Dst = create_oxm_cls()
+OFBIPv6DstID = create_oxm_cls()
+OFBIPv6DstHM = create_oxm_cls()
+OFBIPv6DstHMID = create_oxm_cls()
+OFBIPv6FLabel = create_oxm_cls()
+OFBIPv6FLabelID = create_oxm_cls()
+OFBIPv6FLabelHM = create_oxm_cls()
+OFBIPv6FLabelHMID = create_oxm_cls()
+OFBICMPv6Type = create_oxm_cls()
+OFBICMPv6TypeID = create_oxm_cls()
+OFBICMPv6TypeHM = create_oxm_cls()
+OFBICMPv6TypeHMID = create_oxm_cls()
+OFBICMPv6Code = create_oxm_cls()
+OFBICMPv6CodeID = create_oxm_cls()
+OFBICMPv6CodeHM = create_oxm_cls()
+OFBICMPv6CodeHMID = create_oxm_cls()
+OFBIPv6NDTarget = create_oxm_cls()
+OFBIPv6NDTargetID = create_oxm_cls()
+OFBIPv6NDTargetHM = create_oxm_cls()
+OFBIPv6NDTargetHMID = create_oxm_cls()
+OFBIPv6NDSLL = create_oxm_cls()
+OFBIPv6NDSLLID = create_oxm_cls()
+OFBIPv6NDSLLHM = create_oxm_cls()
+OFBIPv6NDSLLHMID = create_oxm_cls()
+OFBIPv6NDTLL = create_oxm_cls()
+OFBIPv6NDTLLID = create_oxm_cls()
+OFBIPv6NDTLLHM = create_oxm_cls()
+OFBIPv6NDTLLHMID = create_oxm_cls()
+OFBMPLSLabel = create_oxm_cls()
+OFBMPLSLabelID = create_oxm_cls()
+OFBMPLSLabelHM = create_oxm_cls()
+OFBMPLSLabelHMID = create_oxm_cls()
+OFBMPLSTC = create_oxm_cls()
+OFBMPLSTCID = create_oxm_cls()
+OFBMPLSTCHM = create_oxm_cls()
+OFBMPLSTCHMID = create_oxm_cls()
+OFBMPLSBoS = create_oxm_cls()
+OFBMPLSBoSID = create_oxm_cls()
+OFBMPLSBoSHM = create_oxm_cls()
+OFBMPLSBoSHMID = create_oxm_cls()
+OFBPBBISID = create_oxm_cls()
+OFBPBBISIDID = create_oxm_cls()
+OFBPBBISIDHM = create_oxm_cls()
+OFBPBBISIDHMID = create_oxm_cls()
+OFBTunnelID = create_oxm_cls()
+OFBTunnelIDID = create_oxm_cls()
+OFBTunnelIDHM = create_oxm_cls()
+OFBTunnelIDHMID = create_oxm_cls()
+OFBIPv6ExtHdr = create_oxm_cls()
+OFBIPv6ExtHdrID = create_oxm_cls()
+OFBIPv6ExtHdrHM = create_oxm_cls()
+OFBIPv6ExtHdrHMID = create_oxm_cls()
+
+### need_prereq holds a list of prerequisites defined in 7.2.3.8 of the specifications
+### e.g. if you want to use an OFBTCPSrc instance (code 26)
+### you first need to declare an OFBIPProto instance (code 20) with value 6,
+### and if you want to use an OFBIPProto instance (still code 20)
+### you first need to declare an OFBEthType instance (code 10) with value 0x0800
+### (0x0800 means IPv4 by default, but you might want to use 0x86dd with IPv6)
+### need_prereq codes are two times higher than previous oxm classes codes,
+### except for 21 which is sort of a proxy for IPv6 (see below)
+need_prereq = { 14: [12, 0x1000],
+                16: [10, 0x0800],    # could be 0x86dd
+                18: [10, 0x0800],    # could be 0x86dd
+                20: [10, 0x0800],    # could be 0x86dd
+                21: [10, 0x86dd],
+                22: [10, 0x0800],
+                24: [10, 0x0800],
+                26: [20, 6],    
+                28: [20, 6],    
+                30: [20, 17],    
+                32: [20, 17],    
+                34: [20, 132],    
+                36: [20, 132],    
+                38: [20, 1],    
+                40: [20, 1],    
+                42: [10, 0x0806],
+                44: [10, 0x0806],
+                46: [10, 0x0806],
+                48: [10, 0x0806],
+                50: [10, 0x0806],
+                52: [10, 0x86dd],
+                54: [10, 0x86dd],
+                56: [10, 0x86dd],
+                58: [21, 58],        ### small trick here, we refer to normally non-
+                60: [21, 58],        ### existent field 21 to distinguish ipv6
+                62: [58, 135],       # could be 136
+                64: [58, 135],
+                66: [58, 136],
+                68: [10, 0x8847],    # could be 0x8848
+                70: [10, 0x8847],    # could be 0x8848
+                72: [10, 0x8847],    # could be 0x8848
+                74: [10, 0x88e7],
+                78: [10, 0x86dd] }
+
+class OXMPacketListField(PacketListField):
+
+    def __init__(self, name, default, cls, length_from=None, autocomplete=prereq_autocomplete):
+        PacketListField.__init__(self, name, default, cls, length_from=length_from)
+        self.autocomplete = autocomplete
+        self.index = []
+    
+    def i2m(self, pkt, val):
+            ### this part makes for a faster writing of specs-compliant matches
+            ### expect some unwanted behaviour if you try incoherent associations
+            ### you might want to set autocomplete=False in __init__ method
+        if self.autocomplete:
+            # val might be modified during the loop so we need a fixed copy
+            fix_val = copy.deepcopy(val)
+            for oxm in fix_val:
+                f = 2*oxm.field
+                fix_index = list(self.index)
+                while f in need_prereq.keys():
+                # this loop enables a small recursion
+                # e.g. ipv6_nd<--icmpv6<--ip_proto<--eth_type
+                    prereq = need_prereq[f]
+                    f = prereq[0]
+                    f2 = 20 if f == 21 else f       # ipv6 trick...
+                    if f2 not in fix_index:
+                        self.index.insert(0, f2)
+                        prrq = ofp_oxm_cls[f2]()    # never HM
+                        setattr(prrq, ofp_oxm_constr[f2/2][1], prereq[1])
+                        val.insert(0, prrq)
+                    # we could do more complicated stuff to
+                    # make sure prerequisite order is correct
+                    # but it works well when presented with any coherent input
+                    # e.g. you should not mix OFBTCPSrc with OFBICMPv6Code
+                    # and expect to get coherent results...
+                    # you can still go manual by setting prereq_autocomplete=False
+        return val
+
+    def m2i(self, pkt, s):
+        t = struct.unpack("!B", s[2])[0]
+        nrm_t = t - t%2
+        if nrm_t not in self.index:
+            self.index.append(nrm_t)
+        return ofp_oxm_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_oxm_length(s):
+        return struct.unpack("!B", s[3])[0]
+
+    def addfield(self, pkt, s, val):
+        return s + "".join(map(str,self.i2m(pkt, val)))
+
+    def getfield(self, pkt, s):
+        lst = []
+        lim = self.length_from(pkt)
+        ret = s[lim:]
+        remain = s[:lim]
+
+        while remain and len(remain) > 4:
+            l = OXMPacketListField._get_oxm_length(remain) + 4
+            # this could also be done by parsing oxm_fields (fixed lengths)
+            if l <= 4 or len(remain) < l:
+            # no incoherent length
+                break
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        self.index = []
+        ### since OXMPacketListField is called only twice (when OFPMatch and OFPSetField
+        ### classes are created) and not when you want to instantiate an OFPMatch,
+        ### index needs to be reinitialized, otherwise there will be some conflicts
+        ### e.g. if you create OFPMatch with OFBTCPSrc and then change to OFBTCPDst,
+        ### index will already be filled with ethertype and nwproto codes,
+        ### thus the corresponding fields will not be added to the packet
+        return remain + ret, lst
+
+class OXMIDPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!B", s[2])[0]
+        return ofp_oxm_id_cls.get(t, Raw)(s)
+
+    def getfield(self, pkt, s):
+        lst = []
+        lim = self.length_from(pkt)
+        ret = s[lim:]
+        remain = s[:lim]
+
+        while remain and len(remain) >= 4:
+        # all OXM ID are 32-bit long (no experimenter OXM support here)
+            current = remain[:4]
+            remain = remain[4:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain + ret, lst
+
+
+class OFPMatch(Packet):
+    def post_build(self, p, pay):
+        l = self.length
+        if l is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+            zero_bytes = (8 - l%8) % 8
+            p += "\x00" * zero_bytes
+        # message with user-defined length will not be automatically padded
+        return p + pay
+
+    def extract_padding(self, s):
+        l = self.length
+        zero_bytes = (8 - l%8) % 8
+        return s[zero_bytes:], s[:zero_bytes]
+
+    name = "OFP_MATCH"
+    fields_desc= [ ShortEnumField("type", 1, { 0: "OFPMT_STANDARD",
+                                               1: "OFPMT_OXM" }),
+                   ShortField("length", None),
+                   OXMPacketListField("oxm_fields", [], Packet,
+                                      length_from=lambda pkt:pkt.length-4) ]
+
+### ofp_match is no longer a fixed-length structure in v1.3
+### furthermore it may include variable padding
+### we introduce to that end a subclass of PacketField
+class MatchField(PacketField):
+    def __init__(self, name):
+        PacketField.__init__(self, name, OFPMatch(), OFPMatch)
+
+    def getfield(self, pkt, s):
+        i = self.m2i(pkt, s)
+        ### i can be <OFPMatch> or <OFPMatch <Padding>>
+        ### or <OFPMatch <Raw>> or <OFPMatch <Raw <Padding>>>
+        ### and we want to return "", <OFPMatch> or "", <OFPMatch <Padding>>
+        ### or str(<Raw>), <OFPMatch> or str(<Raw>), <OFPMatch <Padding>>
+        if Raw in i:
+            r = i[Raw]
+            if Padding in r:
+                p = r[Padding]
+                i.payload = p
+                del(r.payload)
+            return r.load, i
+        else:
+            return "", i
+
+
+###################### Actions ######################
+
+class _ofp_action_header(Packet):
+    name = "Dummy OpenFlow Action Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+ofp_action_types = {     0: "OFPAT_OUTPUT",
+                         1: "OFPAT_SET_VLAN_VID",
+                         2: "OFPAT_SET_VLAN_PCP",
+                         3: "OFPAT_STRIP_VLAN",
+                         4: "OFPAT_SET_DL_SRC",
+                         5: "OFPAT_SET_DL_DST",
+                         6: "OFPAT_SET_NW_SRC",
+                         7: "OFPAT_SET_NW_DST",
+                         8: "OFPAT_SET_NW_TOS",
+                         9: "OFPAT_SET_TP_SRC",
+                        10: "OFPAT_SET_TP_DST",
+                        #11: "OFPAT_ENQUEUE",
+                        11: "OFPAT_COPY_TTL_OUT",
+                        12: "OFPAT_COPY_TTL_IN",
+                        13: "OFPAT_SET_MPLS_LABEL",
+                        14: "OFPAT_DEC_MPLS_TC",
+                        15: "OFPAT_SET_MPLS_TTL",
+                        16: "OFPAT_DEC_MPLS_TTL",
+                        17: "OFPAT_PUSH_VLAN",
+                        18: "OFPAT_POP_VLAN",
+                        19: "OFPAT_PUSH_MPLS",
+                        20: "OFPAT_POP_MPLS",
+                        21: "OFPAT_SET_QUEUE",
+                        22: "OFPAT_GROUP",
+                        23: "OFPAT_SET_NW_TTL",
+                        24: "OFPAT_DEC_NW_TTL",
+                        25: "OFPAT_SET_FIELD",
+                        26: "OFPAT_PUSH_PBB",
+                        27: "OFPAT_POP_PBB",
+                     65535: "OFPAT_EXPERIMENTER" }
+
+class OFPATOutput(_ofp_action_header):
+    name = "OFPAT_OUTPUT"
+    fields_desc = [ ShortEnumField("type", 0, ofp_action_types),
+                    ShortField("len", 16),
+                    IntEnumField("port", 0, ofp_port_no),
+                    ShortEnumField("max_len", "NO_BUFFER", ofp_max_len),
+                    XBitField("pad", 0, 48) ]
+
+# the following actions are not supported by OFv1.3
+
+class OFPATSetVLANVID(_ofp_action_header):
+    name = "OFPAT_SET_VLAN_VID"
+    fields_desc = [ ShortEnumField("type", 1, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("vlan_vid", 0),
+                    XShortField("pad", 0) ]
+
+class OFPATSetVLANPCP(_ofp_action_header):
+    name = "OFPAT_SET_VLAN_PCP"
+    fields_desc = [ ShortEnumField("type", 2, ofp_action_types),
+                    ShortField("len", 8),
+                    ByteField("vlan_pcp", 0),
+                    X3BytesField("pad", 0) ]
+
+class OFPATStripVLAN(_ofp_action_header):
+    name = "OFPAT_STRIP_VLAN"
+    fields_desc = [ ShortEnumField("type", 3, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATSetDlSrc(_ofp_action_header):
+    name = "OFPAT_SET_DL_SRC"
+    fields_desc = [ ShortEnumField("type", 4, ofp_action_types),
+                    ShortField("len", 16),
+                    MACField("dl_addr", "0"),
+                    XBitField("pad", 0, 48) ]
+
+class OFPATSetDlDst(_ofp_action_header):
+    name = "OFPAT_SET_DL_DST"
+    fields_desc = [ ShortEnumField("type", 5, ofp_action_types),
+                    ShortField("len", 16),
+                    MACField("dl_addr", "0"),
+                    XBitField("pad", 0, 48) ]
+
+class OFPATSetNwSrc(_ofp_action_header):
+    name = "OFPAT_SET_NW_SRC"
+    fields_desc = [ ShortEnumField("type", 6, ofp_action_types),
+                    ShortField("len", 8),
+                    IPField("nw_addr", "0") ]
+
+class OFPATSetNwDst(_ofp_action_header):
+    name = "OFPAT_SET_NW_DST"
+    fields_desc = [ ShortEnumField("type", 7, ofp_action_types),
+                    ShortField("len", 8),
+                    IPField("nw_addr", "0") ]
+
+class OFPATSetNwToS(_ofp_action_header):
+    name = "OFPAT_SET_TP_TOS"
+    fields_desc = [ ShortEnumField("type", 8, ofp_action_types),
+                    ShortField("len", 8),
+                    ByteField("nw_tos", 0),
+                    X3BytesField("pad", 0) ]
+
+class OFPATSetTpSrc(_ofp_action_header):
+    name = "OFPAT_SET_TP_SRC"
+    fields_desc = [ ShortEnumField("type", 9, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("tp_port", 0),
+                    XShortField("pad", 0) ]
+
+class OFPATSetTpDst(_ofp_action_header):
+    name = "OFPAT_SET_TP_DST"
+    fields_desc = [ ShortEnumField("type", 10, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("tp_port", 0),
+                    XShortField("pad", 0) ]
+
+#class OFPATEnqueue(_ofp_action_header):
+#       name = "OFPAT_ENQUEUE"
+#       fields_desc = [ ShortEnumField("type", 11, ofp_action_types),
+#                       ShortField("len", 16),
+#                       ShortField("port", 0),
+#                       XBitField("pad", 0, 48),
+#                       IntEnumField("queue_id", 0, ofp_queue) ]
+
+class OFPATSetMPLSLabel(_ofp_action_header):
+    name = "OFPAT_SET_MPLS_LABEL"
+    fields_desc = [ ShortEnumField("type", 13, ofp_action_types),
+                    ShortField("len", 8),
+                    IntField("mpls_label", 0) ]
+
+class OFPATSetMPLSTC(_ofp_action_header):
+    name = "OFPAT_SET_MPLS_TC"
+    fields_desc = [ ShortEnumField("type", 14, ofp_action_types),
+                    ShortField("len", 8),
+                    ByteField("mpls_tc", 0),
+                    X3BytesField("pad", 0) ]
+
+# end of unsupported actions
+
+class OFPATCopyTTLOut(_ofp_action_header):
+    name = "OFPAT_COPY_TTL_OUT"
+    fields_desc = [ ShortEnumField("type", 11, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATCopyTTLIn(_ofp_action_header):
+    name = "OFPAT_COPY_TTL_IN"
+    fields_desc = [ ShortEnumField("type", 12, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATSetMPLSTTL(_ofp_action_header):
+    name = "OFPAT_SET_MPLS_TTL"
+    fields_desc = [ ShortEnumField("type", 15, ofp_action_types),
+                    ShortField("len", 8),
+                    ByteField("mpls_ttl", 0),
+                    X3BytesField("pad", 0) ]
+
+class OFPATDecMPLSTTL(_ofp_action_header):
+    name = "OFPAT_DEC_MPLS_TTL"
+    fields_desc = [ ShortEnumField("type", 16, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATPushVLAN(_ofp_action_header):
+    name = "OFPAT_PUSH_VLAN"
+    fields_desc = [ ShortEnumField("type", 17, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("ethertype", 0x8100),    # or 0x88a8
+                    XShortField("pad", 0) ]
+
+class OFPATPopVLAN(_ofp_action_header):
+    name = "OFPAT_POP_VLAN"
+    fields_desc = [ ShortEnumField("type", 18, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATPushMPLS(_ofp_action_header):
+    name = "OFPAT_PUSH_MPLS"
+    fields_desc = [ ShortEnumField("type", 19, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("ethertype", 0x8847),    # or 0x8848
+                    XShortField("pad", 0) ]
+
+class OFPATPopMPLS(_ofp_action_header):
+    name = "OFPAT_POP_MPLS"
+    fields_desc = [ ShortEnumField("type", 20, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("ethertype", 0x8847),    # or 0x8848
+                    XShortField("pad", 0) ]
+
+class OFPATSetQueue(_ofp_action_header):
+    name = "OFPAT_SET_QUEUE"
+    fields_desc = [ ShortEnumField("type", 21, ofp_action_types),
+                    ShortField("len", 8),
+                    IntEnumField("queue_id", 0, ofp_queue) ]
+
+class OFPATGroup(_ofp_action_header):
+    name = "OFPAT_GROUP"
+    fields_desc = [ ShortEnumField("type", 22, ofp_action_types),
+                    ShortField("len", 8),
+                    IntEnumField("group_id", 0, ofp_group) ]
+
+class OFPATSetNwTTL(_ofp_action_header):
+    name = "OFPAT_SET_NW_TTL"
+    fields_desc = [ ShortEnumField("type", 23, ofp_action_types),
+                    ShortField("len", 8),
+                    ByteField("nw_ttl", 0),
+                    X3BytesField("pad", 0) ]
+
+class OFPATDecNwTTL(_ofp_action_header):
+    name = "OFPAT_DEC_NW_TTL"
+    fields_desc = [ ShortEnumField("type", 24, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATSetField(_ofp_action_header):
+
+    def post_build(self, p, pay):
+        l = self.len
+        zero_bytes = 0
+        if l is None:
+            l = len(p)+len(pay)
+            zero_bytes = (8 - l%8) % 8
+            l = l + zero_bytes    # add padding length
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        else:
+            zero_bytes = (8 - l%8) % 8
+        # every message will be padded correctly
+        p += "\x00" * zero_bytes
+        return p + pay
+
+    def extract_padding(self, s):
+        return "", s
+
+    name = "OFPAT_SET_FIELD"
+    fields_desc = [ ShortEnumField("type", 25, ofp_action_types),
+                    ShortField("len", None),
+                    # there should not be more than one oxm tlv
+                    OXMPacketListField("field", [], Packet,
+                                       length_from=lambda pkt:pkt.len-4,
+                                       # /!\ contains padding!
+                                       autocomplete=False) ]
+
+class OFPATPushPBB(_ofp_action_header):
+    name = "OFPAT_PUSH_PBB"
+    fields_desc = [ ShortEnumField("type", 26, ofp_action_types),
+                    ShortField("len", 8),
+                    ShortField("ethertype", 0x88e7),
+                    XShortField("pad", 0) ]
+
+class OFPATPopPBB(_ofp_action_header):
+    name = "OFPAT_POP_PBB"
+    fields_desc = [ ShortEnumField("type", 27, ofp_action_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPATExperimenter(_ofp_action_header):
+    name = "OFPAT_EXPERIMENTER"
+    fields_desc = [ ShortEnumField("type", 65535, ofp_action_types),
+                    ShortField("len", 8),
+                    IntField("experimenter", 0) ]
+
+ofp_action_cls = {     0: OFPATOutput,
+                       1: OFPATSetVLANVID,
+                       2: OFPATSetVLANPCP,
+                       3: OFPATStripVLAN,
+                       4: OFPATSetDlSrc,
+                       5: OFPATSetDlDst,
+                       6: OFPATSetNwSrc,
+                       7: OFPATSetNwDst,
+                       8: OFPATSetNwToS,
+                       9: OFPATSetTpSrc,
+                      10: OFPATSetTpDst,
+                      #11: OFPATEnqueue,
+                      11: OFPATCopyTTLOut,
+                      12: OFPATCopyTTLIn,
+                      13: OFPATSetMPLSLabel,
+                      14: OFPATSetMPLSTC,
+                      15: OFPATSetMPLSTTL,
+                      16: OFPATDecMPLSTTL,
+                      17: OFPATPushVLAN,
+                      18: OFPATPopVLAN,
+                      19: OFPATPushMPLS,
+                      20: OFPATPopMPLS,
+                      21: OFPATSetQueue,
+                      22: OFPATGroup,
+                      23: OFPATSetNwTTL,
+                      24: OFPATDecNwTTL,
+                      25: OFPATSetField,
+                      26: OFPATPushPBB,
+                      27: OFPATPopPBB,
+                   65535: OFPATExperimenter }
+
+class ActionPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_action_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_action_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain and len(remain)>=4:
+            l = ActionPacketListField._get_action_length(remain)
+            if l < 8 or len(remain) < l:
+              # length should be at least 8 (non-zero, 64-bit aligned),
+              # and no incoherent length
+              break
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+
+##################### Action IDs ####################
+
+# length is computed as in instruction structures,
+# so we reuse _ofp_instruction_header
+
+class OFPATOutputID(_ofp_action_header):
+    name = "OFPAT_OUTPUT"
+    fields_desc = [ ShortEnumField("type", 0, ofp_action_types),
+                    ShortField("len", 4) ]
+
+# the following actions are not supported by OFv1.3
+
+class OFPATSetVLANVIDID(_ofp_action_header):
+    name = "OFPAT_SET_VLAN_VID"
+    fields_desc = [ ShortEnumField("type", 1, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetVLANPCPID(_ofp_action_header):
+    name = "OFPAT_SET_VLAN_PCP"
+    fields_desc = [ ShortEnumField("type", 2, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATStripVLANID(_ofp_action_header):
+    name = "OFPAT_STRIP_VLAN"
+    fields_desc = [ ShortEnumField("type", 3, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetDlSrcID(_ofp_action_header):
+    name = "OFPAT_SET_DL_SRC"
+    fields_desc = [ ShortEnumField("type", 4, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetDlDstID(_ofp_action_header):
+    name = "OFPAT_SET_DL_DST"
+    fields_desc = [ ShortEnumField("type", 5, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetNwSrcID(_ofp_action_header):
+    name = "OFPAT_SET_NW_SRC"
+    fields_desc = [ ShortEnumField("type", 6, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetNwDstID(_ofp_action_header):
+    name = "OFPAT_SET_NW_DST"
+    fields_desc = [ ShortEnumField("type", 7, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetNwToSID(_ofp_action_header):
+    name = "OFPAT_SET_TP_TOS"
+    fields_desc = [ ShortEnumField("type", 8, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetTpSrcID(_ofp_action_header):
+    name = "OFPAT_SET_TP_SRC"
+    fields_desc = [ ShortEnumField("type", 9, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetTpDstID(_ofp_action_header):
+    name = "OFPAT_SET_TP_DST"
+    fields_desc = [ ShortEnumField("type", 10, ofp_action_types),
+                    ShortField("len", 4) ]
+
+#class OFPATEnqueueID(_ofp_action_header):
+#       name = "OFPAT_ENQUEUE"
+#       fields_desc = [ ShortEnumField("type", 11, ofp_action_types),
+#                       ShortField("len", 4) ]
+
+class OFPATSetMPLSLabelID(_ofp_action_header):
+    name = "OFPAT_SET_MPLS_LABEL"
+    fields_desc = [ ShortEnumField("type", 13, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetMPLSTCID(_ofp_action_header):
+    name = "OFPAT_SET_MPLS_TC"
+    fields_desc = [ ShortEnumField("type", 14, ofp_action_types),
+                    ShortField("len", 4) ]
+
+# end of unsupported actions
+
+class OFPATCopyTTLOutID(_ofp_action_header):
+    name = "OFPAT_COPY_TTL_OUT"
+    fields_desc = [ ShortEnumField("type", 11, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATCopyTTLInID(_ofp_action_header):
+    name = "OFPAT_COPY_TTL_IN"
+    fields_desc = [ ShortEnumField("type", 12, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetMPLSTTLID(_ofp_action_header):
+    name = "OFPAT_SET_MPLS_TTL"
+    fields_desc = [ ShortEnumField("type", 15, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATDecMPLSTTLID(_ofp_action_header):
+    name = "OFPAT_DEC_MPLS_TTL"
+    fields_desc = [ ShortEnumField("type", 16, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATPushVLANID(_ofp_action_header):
+    name = "OFPAT_PUSH_VLAN"
+    fields_desc = [ ShortEnumField("type", 17, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATPopVLANID(_ofp_action_header):
+    name = "OFPAT_POP_VLAN"
+    fields_desc = [ ShortEnumField("type", 18, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATPushMPLSID(_ofp_action_header):
+    name = "OFPAT_PUSH_MPLS"
+    fields_desc = [ ShortEnumField("type", 19, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATPopMPLSID(_ofp_action_header):
+    name = "OFPAT_POP_MPLS"
+    fields_desc = [ ShortEnumField("type", 20, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetQueueID(_ofp_action_header):
+    name = "OFPAT_SET_QUEUE"
+    fields_desc = [ ShortEnumField("type", 21, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATGroupID(_ofp_action_header):
+    name = "OFPAT_GROUP"
+    fields_desc = [ ShortEnumField("type", 22, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetNwTTLID(_ofp_action_header):
+    name = "OFPAT_SET_NW_TTL"
+    fields_desc = [ ShortEnumField("type", 23, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATDecNwTTLID(_ofp_action_header):
+    name = "OFPAT_DEC_NW_TTL"
+    fields_desc = [ ShortEnumField("type", 24, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATSetFieldID(_ofp_action_header):
+    name = "OFPAT_SET_FIELD"
+    fields_desc = [ ShortEnumField("type", 25, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATPushPBBID(_ofp_action_header):
+    name = "OFPAT_PUSH_PBB"
+    fields_desc = [ ShortEnumField("type", 26, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATPopPBBID(_ofp_action_header):
+    name = "OFPAT_POP_PBB"
+    fields_desc = [ ShortEnumField("type", 27, ofp_action_types),
+                    ShortField("len", 4) ]
+
+class OFPATExperimenterID(_ofp_action_header):
+    name = "OFPAT_EXPERIMENTER"
+    fields_desc = [ ShortEnumField("type", 65535, ofp_action_types),
+                    ShortField("len", None) ]
+
+ofp_action_id_cls = {     0: OFPATOutputID,
+                          1: OFPATSetVLANVIDID,
+                          2: OFPATSetVLANPCPID,
+                          3: OFPATStripVLANID,
+                          4: OFPATSetDlSrcID,
+                          5: OFPATSetDlDstID,
+                          6: OFPATSetNwSrcID,
+                          7: OFPATSetNwDstID,
+                          8: OFPATSetNwToSID,
+                          9: OFPATSetTpSrcID,
+                         10: OFPATSetTpDstID,
+                         #11: OFPATEnqueueID,
+                         11: OFPATCopyTTLOutID,
+                         12: OFPATCopyTTLInID,
+                         13: OFPATSetMPLSLabelID,
+                         14: OFPATSetMPLSTCID,
+                         15: OFPATSetMPLSTTLID,
+                         16: OFPATDecMPLSTTLID,
+                         17: OFPATPushVLANID,
+                         18: OFPATPopVLANID,
+                         19: OFPATPushMPLSID,
+                         20: OFPATPopMPLSID,
+                         21: OFPATSetQueueID,
+                         22: OFPATGroupID,
+                         23: OFPATSetNwTTLID,
+                         24: OFPATDecNwTTLID,
+                         25: OFPATSetFieldID,
+                         26: OFPATPushPBBID,
+                         27: OFPATPopPBBID,
+                      65535: OFPATExperimenterID }
+
+class ActionIDPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_action_id_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_action_id_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain and len(remain) >= 4:
+            l = ActionIDPacketListField._get_action_id_length(remain)
+            if l < 4 or len(remain) < l:
+            # length is 4 (may be more for experimenter messages),
+            # and no incoherent length
+                break
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+
+#################### Instructions ###################
+
+class _ofp_instruction_header(Packet):
+    name = "Dummy OpenFlow Instruction Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+ofp_instruction_types = {     1: "OFPIT_GOTO_TABLE",
+                              2: "OFPIT_WRITE_METADATA",
+                              3: "OFPIT_WRITE_ACTIONS",
+                              4: "OFPIT_APPLY_ACTIONS",
+                              5: "OFPIT_CLEAR_ACTIONS",
+                              6: "OFPIT_METER",
+                          65535: "OFPIT_EXPERIMENTER" }
+
+class OFPITGotoTable(_ofp_instruction_header):
+    name = "OFPIT_GOTO_TABLE"
+    fields_desc = [ ShortEnumField("type", 1, ofp_instruction_types),
+                    ShortField("len", 8),
+                    ByteEnumField("table_id", 0, ofp_table),
+                    X3BytesField("pad", 0) ]
+
+class OFPITWriteMetadata(_ofp_instruction_header):
+    name = "OFPIT_WRITE_METADATA"
+    fields_desc = [ ShortEnumField("type", 2, ofp_instruction_types),
+                    ShortField("len", 24),
+                    XIntField("pad", 0),
+                    LongField("metadata", 0),
+                    LongField("metadata_mask", 0) ]
+
+class OFPITWriteActions(_ofp_instruction_header):
+    name = "OFPIT_WRITE_ACTIONS"
+    fields_desc = [ ShortEnumField("type", 3, ofp_instruction_types),
+                    ShortField("len", None),
+                    XIntField("pad", 0),
+                    ActionPacketListField("actions", [], Packet,
+                                          length_from=lambda pkt:pkt.len-8) ]
+
+class OFPITApplyActions(_ofp_instruction_header):
+    name = "OFPIT_APPLY_ACTIONS"
+    fields_desc = [ ShortEnumField("type", 4, ofp_instruction_types),
+                    ShortField("len", None),
+                    XIntField("pad", 0),
+                    ActionPacketListField("actions", [], Packet,
+                                          length_from=lambda pkt:pkt.len-8) ]
+
+class OFPITClearActions(_ofp_instruction_header):
+    name = "OFPIT_CLEAR_ACTIONS"
+    fields_desc = [ ShortEnumField("type", 5, ofp_instruction_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPITMeter(_ofp_instruction_header):
+    name = "OFPIT_METER"
+    fields_desc = [ ShortEnumField("type", 6, ofp_instruction_types),
+                    ShortField("len", 8),
+                    IntEnumField("meter_id", 1, ofp_meter) ]
+
+class OFPITExperimenter(_ofp_instruction_header):
+    name = "OFPIT_EXPERIMENTER"
+    fields_desc = [ ShortEnumField("type", 65535, ofp_instruction_types),
+                    ShortField("len", None),
+                    IntField("experimenter", 0) ]
+
+ofp_instruction_cls = {     1: OFPITGotoTable,
+                            2: OFPITWriteMetadata,
+                            3: OFPITWriteActions,
+                            4: OFPITApplyActions,
+                            5: OFPITClearActions,
+                            6: OFPITMeter,
+                        65535: OFPITExperimenter }
+
+class InstructionPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_instruction_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_instruction_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain and len(remain) > 4:
+            l = InstructionPacketListField._get_instruction_length(remain)
+            if l < 8 or len(remain) < l:
+            # length should be at least 8 (non-zero, 64-bit aligned),
+            # and no incoherent length
+                break
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+
+################## Instruction IDs ##################
+
+# length is computed as in instruction structures,
+# so we reuse _ofp_instruction_header
+
+class OFPITGotoTableID(_ofp_instruction_header):
+    name = "OFPIT_GOTO_TABLE"
+    fields_desc = [ ShortEnumField("type", 1, ofp_instruction_types),
+                    ShortField("len", 4) ]
+
+class OFPITWriteMetadataID(_ofp_instruction_header):
+    name = "OFPIT_WRITE_METADATA"
+    fields_desc = [ ShortEnumField("type", 2, ofp_instruction_types),
+                    ShortField("len", 4) ]
+
+class OFPITWriteActionsID(_ofp_instruction_header):
+    name = "OFPIT_WRITE_ACTIONS"
+    fields_desc = [ ShortEnumField("type", 3, ofp_instruction_types),
+                    ShortField("len", 4) ]
+
+class OFPITApplyActionsID(_ofp_instruction_header):
+    name = "OFPIT_APPLY_ACTIONS"
+    fields_desc = [ ShortEnumField("type", 4, ofp_instruction_types),
+                    ShortField("len", 4) ]
+
+class OFPITClearActionsID(_ofp_instruction_header):
+    name = "OFPIT_CLEAR_ACTIONS"
+    fields_desc = [ ShortEnumField("type", 5, ofp_instruction_types),
+                    ShortField("len", 4) ]
+
+class OFPITMeterID(_ofp_instruction_header):
+    name = "OFPIT_METER"
+    fields_desc = [ ShortEnumField("type", 6, ofp_instruction_types),
+                    ShortField("len", 4) ]
+
+class OFPITExperimenterID(_ofp_instruction_header):
+    name = "OFPIT_EXPERIMENTER"
+    fields_desc = [ ShortEnumField("type", 65535, ofp_instruction_types),
+                    ShortField("len", None) ]
+
+ofp_instruction_id_cls = {     1: OFPITGotoTableID,
+                               2: OFPITWriteMetadataID,
+                               3: OFPITWriteActionsID,
+                               4: OFPITApplyActionsID,
+                               5: OFPITClearActionsID,
+                               6: OFPITMeterID,
+                           65535: OFPITExperimenterID }
+
+class InstructionIDPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_instruction_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_instruction_id_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain and len(remain) >= 4:
+            l = InstructionIDPacketListField._get_instruction_id_length(remain)
+            if l < 4 or len(remain) < l:
+            # length is 4 (may be more for experimenter messages),
+            # and no incoherent length
+                break
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+
+###################### Buckets ######################
+
+class OFPBucket(Packet):
+
+    def extract_padding(self, s):
+        return "", s
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = struct.pack("!H", l) + p[2:]
+        return p + pay
+
+    name = "OFP_BUCKET"
+    fields_desc = [ ShortField("len", None),
+                    ShortField("weight", 0),
+                    IntEnumField("watch_port", 0, ofp_port_no),
+                    IntEnumField("watch_group", 0, ofp_group),
+                    XIntField("pad", 0),
+                    ActionPacketListField("actions", [], Packet,
+                                          length_from=lambda pkt:pkt.len-16) ]
+
+class BucketPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_bucket_length(s):
+        return struct.unpack("!H", s[:2])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = BucketPacketListField._get_bucket_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPBucket(current)
+            lst.append(p)
+
+        return remain, lst
+
+
+####################### Queues ######################
+
+class _ofp_queue_property_header(Packet):
+    name = "Dummy OpenFlow Queue Property Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+ofp_queue_property_types = { 0: "OFPQT_NONE",
+                             1: "OFPQT_MIN_RATE" }
+
+class OFPQTNone(_ofp_queue_property_header):
+    name = "OFPQT_NONE"
+    fields_desc = [ ShortEnumField("type", 0, ofp_queue_property_types),
+                    ShortField("len", 8),
+                    XIntField("pad", 0) ]
+
+class OFPQTMinRate(_ofp_queue_property_header):
+    name = "OFPQT_MIN_RATE"
+    fields_desc = [ ShortEnumField("type", 1, ofp_queue_property_types),
+                    ShortField("len", 16),
+                    XIntField("pad1", 0),
+                    ShortField("rate", 0),
+                    XBitField("pad2", 0, 48) ]
+
+ofp_queue_property_cls = { 0: OFPQTNone,
+                           1: OFPQTMinRate }
+
+class QueuePropertyPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_queue_property_cls.get(t, Raw)(s)
+
+    @staticmethod
+    def _get_queue_property_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = QueuePropertyPacketListField._get_queue_property_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+class OFPPacketQueue(Packet):
+
+    def extract_padding(self, s):
+        return "", s
+
+    def post_build(self, p, pay):
+        if self.properties == []:
+            p += str(OFPQTNone())
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:4] + struct.pack("!H", l) + p[6:]
+        return p + pay
+
+    name = "OFP_PACKET_QUEUE"
+    fields_desc = [ IntEnumField("queue_id", 0, ofp_queue),
+                    ShortField("len", None),
+                    XShortField("pad", 0),
+                    QueuePropertyPacketListField("properties", [], Packet,
+                                                 length_from=lambda pkt:pkt.len-8) ]
+
+class QueuePacketListField(PacketListField):
+
+    @staticmethod
+    def _get_queue_length(s):
+        return struct.unpack("!H", s[4:6])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = QueuePacketListField._get_queue_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPPacketQueue(current)
+            lst.append(p)
+
+        return remain, lst
+
+
+#################### Meter bands ####################
+
+ofp_meter_band_types = {     0: "OFPMBT_DROP",
+                             1: "OFPMBT_DSCP_REMARK",
+                         65535: "OFPMBT_EXPERIMENTER" }
+
+class OFPMBTDrop(Packet):
+    name = "OFPMBT_DROP"
+    fields_desc = [ ShortEnumField("type", 0, ofp_queue_property_types),
+                    ShortField("len", 16),
+                    IntField("rate", 0),
+                    IntField("burst_size", 0),
+                    XIntField("pad", 0) ]
+
+class OFPMBTDSCPRemark(Packet):
+    name = "OFPMBT_DSCP_REMARK"
+    fields_desc = [ ShortEnumField("type", 1, ofp_queue_property_types),
+                    ShortField("len", 16),
+                    IntField("rate", 0),
+                    IntField("burst_size", 0),
+                    ByteField("prec_level", 0),
+                    X3BytesField("pad", 0) ]
+
+class OFPMBTExperimenter(Packet):
+    name = "OFPMBT_EXPERIMENTER"
+    fields_desc = [ ShortEnumField("type", 65535, ofp_queue_property_types),
+                    ShortField("len", 16),
+                    IntField("rate", 0),
+                    IntField("burst_size", 0),
+                    IntField("experimenter", 0) ]
+
+ofp_meter_band_cls = { 0: OFPMBTDrop,
+                       1: OFPMBTDSCPRemark,
+                       2: OFPMBTExperimenter }
+
+class MeterBandPacketListField(PacketListField):
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_meter_band_cls.get(t, Raw)(s)
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            current = remain[:16]
+            remain = remain[16:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+
+#####################################################
+############## OpenFlow 1.3 Messages ################
+#####################################################
+
+ofp_version = { 0x01: "OpenFlow 1.0",
+                0x02: "OpenFlow 1.1",
+                0x03: "OpenFlow 1.2",
+                0x04: "OpenFlow 1.3",
+                0x05: "OpenFlow 1.4" }
+
+ofp_type = {  0: "OFPT_HELLO",
+              1: "OFPT_ERROR",
+              2: "OFPT_ECHO_REQUEST",
+              3: "OFPT_ECHO_REPLY",
+              4: "OFPT_EXPERIMENTER",
+              5: "OFPT_FEATURES_REQUEST",
+              6: "OFPT_FEATURES_REPLY",
+              7: "OFPT_GET_CONFIG_REQUEST",
+              8: "OFPT_GET_CONFIG_REPLY",
+              9: "OFPT_SET_CONFIG",
+             10: "OFPT_PACKET_IN",
+             11: "OFPT_FLOW_REMOVED",
+             12: "OFPT_PORT_STATUS",
+             13: "OFPT_PACKET_OUT",
+             14: "OFPT_FLOW_MOD",
+             15: "OFPT_GROUP_MOD",
+             16: "OFPT_PORT_MOD",
+             17: "OFPT_TABLE_MOD",
+             18: "OFPT_MULTIPART_REQUEST",
+             19: "OFPT_MULTIPART_REPLY",
+             20: "OFPT_BARRIER_REQUEST",
+             21: "OFPT_BARRIER_REPLY",
+             22: "OFPT_QUEUE_GET_CONFIG_REQUEST",
+             23: "OFPT_QUEUE_GET_CONFIG_REPLY",
+             24: "OFPT_ROLE_REQUEST",
+             25: "OFPT_ROLE_REPLY",
+             26: "OFPT_GET_ASYNC_REQUEST",
+             27: "OFPT_GET_ASYNC_REPLY",
+             28: "OFPT_SET_ASYNC",
+             29: "OFPT_METER_MOD" }
+
+class _ofp_header(Packet):
+    name = "Dummy OpenFlow Header"
+
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        return p + pay
+
+class OFPTHello(_ofp_header):
+    name = "OFPT_HELLO"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 0, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    HelloElemPacketListField("elements", [], Packet,
+                                             length_from=lambda pkt:pkt.len-32) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+#####################################################
+##################### OFPT_ERROR ####################
+#####################################################
+
+### this class will be used to display some messages
+### sent back by the switch after an error
+class OFPacketField(PacketField):
+    def getfield(self, pkt, s):
+        try:
+            l = s[2:4]
+            l = struct.unpack("!H", l)[0]
+            ofload = s[:l]
+            remain = s[l:]
+            return remain, OpenFlow(None, ofload)(ofload)
+        except:
+            return "", Raw(s)
+
+ofp_error_type = {     0: "OFPET_HELLO_FAILED",
+                       1: "OFPET_BAD_REQUEST",
+                       2: "OFPET_BAD_ACTION",
+                       3: "OFPET_BAD_INSTRUCTION",
+                       4: "OFPET_BAD_MATCH",
+                       5: "OFPET_FLOW_MOD_FAILED",
+                       6: "OFPET_GROUP_MOD_FAILED",
+                       7: "OFPET_PORT_MOD_FAILED",
+                       8: "OFPET_TABLE_MOD_FAILED",
+                       9: "OFPET_QUEUE_OP_FAILED",
+                      10: "OFPET_SWITCH_CONFIG_FAILED",
+                      11: "OFPET_ROLE_REQUEST_FAILED",
+                      12: "OFPET_METER_MOD_FAILED",
+                      13: "OFPET_TABLE_FEATURES_FAILED",
+                   65535: "OFPET_EXPERIMENTER" }
+
+class OFPETHelloFailed(_ofp_header):
+    name = "OFPET_HELLO_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 0, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPHFC_INCOMPATIBLE",
+                                                   1: "OFPHFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETBadRequest(_ofp_header):
+    name = "OFPET_BAD_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 1, ofp_error_type),
+                    ShortEnumField("errcode", 0, {  0: "OFPBRC_BAD_VERSION",
+                                                    1: "OFPBRC_BAD_TYPE",
+                                                    2: "OFPBRC_BAD_MULTIPART",
+                                                    3: "OFPBRC_BAD_EXPERIMENTER",
+                                                    4: "OFPBRC_BAD_EXP_TYPE",
+                                                    5: "OFPBRC_EPERM",
+                                                    6: "OFPBRC_BAD_LEN",
+                                                    7: "OFPBRC_BUFFER_EMPTY",
+                                                    8: "OFPBRC_BUFFER_UNKNOWN",
+                                                    9: "OFPBRC_BAD_TABLE_ID",
+                                                   10: "OFPBRC_IS_SLAVE",
+                                                   11: "OFPBRC_BAD_PORT",
+                                                   12: "OFPBRC_BAD_PACKET",
+                                                   13: "OFPBRC_MULTIPART_BUFFER_OVERFLOW" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETBadAction(_ofp_header):
+    name = "OFPET_BAD_ACTION"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 2, ofp_error_type),
+                    ShortEnumField("errcode", 0, {  0: "OFPBAC_BAD_TYPE",
+                                                    1: "OFPBAC_BAD_LEN",
+                                                    2: "OFPBAC_BAD_EXPERIMENTER",
+                                                    3: "OFPBAC_BAD_EXP_TYPE",
+                                                    4: "OFPBAC_BAD_OUT_PORT",
+                                                    5: "OFPBAC_BAD_ARGUMENT",
+                                                    6: "OFPBAC_EPERM",
+                                                    7: "OFPBAC_TOO_MANY",
+                                                    8: "OFPBAC_BAD_QUEUE",
+                                                    9: "OFPBAC_BAD_OUT_GROUP",
+                                                   10: "OFPBAC_MATCH_INCONSISTENT",
+                                                   11: "OFPBAC_UNSUPPORTED_ORDER",
+                                                   12: "OFPBAC_BAD_TAG",
+                                                   13: "OFPBAC_BAD_SET_TYPE",
+                                                   14: "OFPBAC_BAD_SET_LEN",
+                                                   15: "OFPBAC_BAD_SET_ARGUMENT" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETBadInstruction(_ofp_header):
+    name = "OFPET_BAD_INSTRUCTION"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 3, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPBIC_UNKNOWN_INST",
+                                                   1: "OFPBIC_UNSUP_INST",
+                                                   2: "OFPBIC_BAD_TABLE_ID",
+                                                   3: "OFPBIC_UNSUP_METADATA",
+                                                   4: "OFPBIC_UNSUP_METADATA_MASK",
+                                                   5: "OFPBIC_BAD_EXPERIMENTER",
+                                                   6: "OFPBIC_BAD_EXP_TYPE",
+                                                   7: "OFPBIC_BAD_LEN",
+                                                   8: "OFPBIC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETBadMatch(_ofp_header):
+    name = "OFPET_BAD_MATCH"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 4, ofp_error_type),
+                    ShortEnumField("errcode", 0, {  0: "OFPBMC_BAD_TYPE",
+                                                    1: "OFPBMC_BAD_LEN",
+                                                    2: "OFPBMC_BAD_TAG",
+                                                    3: "OFPBMC_BAD_DL_ADDR_MASK",
+                                                    4: "OFPBMC_BAD_NW_ADDR_MASK",
+                                                    5: "OFPBMC_BAD_WILDCARDS",
+                                                    6: "OFPBMC_BAD_FIELD",
+                                                    7: "OFPBMC_BAD_VALUE",
+                                                    8: "OFPBMC_BAD_MASK",
+                                                    9: "OFPBMC_BAD_PREREQ",
+                                                   10: "OFPBMC_DUP_FIELD",
+                                                   11: "OFPBMC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETFlowModFailed(_ofp_header):
+    name = "OFPET_FLOW_MOD_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 5, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPFMFC_UNKNOWN",
+                                                   1: "OFPFMFC_TABLE_FULL",
+                                                   2: "OFPFMFC_BAD_TABLE_ID",
+                                                   3: "OFPFMFC_OVERLAP",
+                                                   4: "OFPFMFC_EPERM",
+                                                   5: "OFPFMFC_BAD_TIMEOUT",
+                                                   6: "OFPFMFC_BAD_COMMAND",
+                                                   7: "OFPFMFC_BAD_FLAGS" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETGroupModFailed(_ofp_header):
+    name = "OFPET_GROUP_MOD_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 6, ofp_error_type),
+                    ShortEnumField("errcode", 0, {  0: "OFPGMFC_GROUP_EXISTS",
+                                                    1: "OFPGMFC_INVALID_GROUP",
+                                                    2: "OFPGMFC_WEIGHT_UNSUPPORTED",
+                                                    3: "OFPGMFC_OUT_OF_GROUPS",
+                                                    4: "OFPGMFC_OUT_OF_BUCKETS",
+                                                    5: "OFPGMFC_CHAINING_UNSUPPORTED",
+                                                    6: "OFPGMFC_WATCH_UNSUPPORTED",
+                                                    7: "OFPGMFC_LOOP",
+                                                    8: "OFPGMFC_UNKNOWN_GROUP",
+                                                    9: "OFPGMFC_CHAINED_GROUP",
+                                                   10: "OFPGMFC_BAD_TYPE",
+                                                   11: "OFPGMFC_BAD_COMMAND",
+                                                   12: "OFPGMFC_BAD_BUCKET",
+                                                   13: "OFPGMFC_BAD_WATCH",
+                                                   14: "OFPFMFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETPortModFailed(_ofp_header):
+    name = "OFPET_PORT_MOD_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 7, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPPMFC_BAD_PORT",
+                                                   1: "OFPPMFC_BAD_HW_ADDR",
+                                                   2: "OFPPMFC_BAD_CONFIG",
+                                                   3: "OFPPMFC_BAD_ADVERTISE",
+                                                   4: "OFPPMFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETTableModFailed(_ofp_header):
+    name = "OFPET_TABLE_MOD_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 8, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPTMFC_BAD_TABLE",
+                                                   1: "OFPTMFC_BAD_CONFIG",
+                                                   2: "OFPTMFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETQueueOpFailed(_ofp_header):
+    name = "OFPET_QUEUE_OP_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 9, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPQOFC_BAD_PORT",
+                                                   1: "OFPQOFC_BAD_QUEUE",
+                                                   2: "OFPQOFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETSwitchConfigFailed(_ofp_header):
+    name = "OFPET_SWITCH_CONFIG_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 10, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPSCFC_BAD_FLAGS",
+                                                   1: "OFPSCFC_BAD_LEN",
+                                                   2: "OFPSCFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETRoleRequestFailed(_ofp_header):
+    name = "OFPET_ROLE_REQUEST_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 11, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPRRFC_STALE",
+                                                   1: "OFPRRFC_UNSUP",
+                                                   2: "OFPRRFC_BAD_ROLE" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETMeterModFailed(_ofp_header):
+    name = "OFPET_METER_MOD_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 12, ofp_error_type),
+                    ShortEnumField("errcode", 0, {  0: "OFPMMFC_UNKNOWN",
+                                                    1: "OFPMMFC_METER_EXISTS",
+                                                    2: "OFPMMFC_INVALID_METER",
+                                                    3: "OFPMMFC_UNKNOWN_METER",
+                                                    4: "OFPMMFC_BAD_COMMAND",
+                                                    5: "OFPMMFC_BAD_FLAGS",
+                                                    6: "OFPMMFC_BAD_RATE",
+                                                    7: "OFPMMFC_BAD_BURST",
+                                                    8: "OFPMMFC_BAD_BAND",
+                                                    9: "OFPMMFC_BAD_BAND_VALUE",
+                                                   10: "OFPMMFC_OUT_OF_METERS",
+                                                   11: "OFPMMFC_OUT_OF_BANDS" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETTableFeaturesFailed(_ofp_header):
+    name = "OFPET_TABLE_FEATURES_FAILED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", 13, ofp_error_type),
+                    ShortEnumField("errcode", 0, { 0: "OFPTFFC_BAD_TABLE",
+                                                   1: "OFPTFFC_BAD_METADATA",
+                                                   2: "OFPTFFC_BAD_TYPE",
+                                                   3: "OFPTFFC_BAD_LEN",
+                                                   4: "OFPTFFC_BAD_ARGUMENT",
+                                                   5: "OFPTFFC_EPERM" }),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPETExperimenter(_ofp_header):
+    name = "OFPET_EXPERIMENTER"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 1, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("errtype", "OFPET_EXPERIMENTER", ofp_error_type),
+                    ShortField("exp_type", None),
+                    IntField("experimenter", None),
+                    OFPacketField("data", "", Raw) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+# ofp_error_cls allows generic method OpenFlow()
+# to choose the right class for dissection
+ofp_error_cls = {     0: OFPETHelloFailed,
+                      1: OFPETBadRequest,
+                      2: OFPETBadAction,
+                      3: OFPETBadInstruction,
+                      4: OFPETBadMatch,
+                      5: OFPETFlowModFailed,
+                      6: OFPETGroupModFailed,
+                      7: OFPETPortModFailed,
+                      8: OFPETTableModFailed,
+                      9: OFPETQueueOpFailed,
+                     10: OFPETSwitchConfigFailed,
+                     11: OFPETRoleRequestFailed,
+                     12: OFPETMeterModFailed,
+                     13: OFPETTableFeaturesFailed,
+                  65535: OFPETExperimenter }
+
+################ end of OFPT_ERRORS #################
+
+class OFPTEchoRequest(_ofp_header):
+    name = "OFPT_ECHO_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 2, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTEchoReply(_ofp_header):
+    name = "OFPT_ECHO_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 3, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTExperimenter(_ofp_header):
+    name = "OFPT_EXPERIMENTER"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 4, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntField("experimenter", 0),
+                    IntField("exp_type", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTFeaturesRequest(_ofp_header):
+    name = "OFPT_FEATURES_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 5, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTFeaturesReply(_ofp_header):
+    name = "OFPT_FEATURES_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 6, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    LongField("datapath_id", 0),
+                    IntField("n_buffers", 0),
+                    ByteField("n_tables", 1),
+                    ByteField("auxiliary_id", 0),
+                    XShortField("pad", 0),
+                    FlagsField("capabilities", 0, 32, [ "FLOW_STATS",
+                                                        "TABLE_STATS",
+                                                        "PORT_STATS",
+                                                        "GROUP_STATS",
+                                                        "RESERVED",       #undefined
+                                                        "IP_REASM",
+                                                        "QUEUE_STATS",
+                                                        "ARP_MATCH_IP",   #undefined
+                                                        "PORT_BLOCKED"]),
+                    IntField("reserved", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTGetConfigRequest(_ofp_header):
+    name = "OFPT_GET_CONFIG_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 7, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTGetConfigReply(_ofp_header):
+    name = "OFPT_GET_CONFIG_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 8, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("flags", 0, { 0: "FRAG_NORMAL",
+                                                 1: "FRAG_DROP",
+                                                 2: "FRAG_REASM",
+                                                 3: "FRAG_MASK" }),
+                    ShortField("miss_send_len", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTSetConfig(_ofp_header):
+    name = "OFPT_SET_CONFIG"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 9, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("flags", 0, { 0: "FRAG_NORMAL",
+                                                 1: "FRAG_DROP",
+                                                 2: "FRAG_REASM",
+                                                 3: "FRAG_MASK" }),
+                    ShortField("miss_send_len", 128) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTPacketIn(_ofp_header):
+    name = "OFPT_PACKET_IN"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 10, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
+                    ShortField("total_len", 0),
+                    ByteEnumField("reason", 0, { 0: "OFPR_NO_MATCH",
+                                                 1: "OFPR_ACTION",
+                                                 2: "OFPR_INVALID_TTL"}),
+                    ByteEnumField("table_id", 0, ofp_table),
+                    LongField("cookie", 0),
+                    MatchField("match"),
+                    XShortField("pad", 0),
+                    PacketField("data", "", Ether) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTFlowRemoved(_ofp_header):
+    name = "OFPT_FLOW_REMOVED"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 11, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    LongField("cookie", 0),
+                    ShortField("priority", 0),
+                    ByteEnumField("reason", 0, { 0: "OFPRR_IDLE_TIMEOUT",
+                                                 1: "OFPRR_HARD_TIMEOUT",
+                                                 2: "OFPRR_DELETE",
+                                                 3: "OFPRR_GROUP_DELETE"}),
+                    ByteEnumField("table_id", 0, ofp_table),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0),
+                    ShortField("idle_timeout", 0),
+                    ShortField("hard_timeout", 0),
+                    LongField("packet_count", 0),
+                    LongField("byte_count", 0),
+                    MatchField("match") ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTPortStatus(_ofp_header):
+    name = "OFPT_PORT_STATUS"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 12, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ByteEnumField("reason", 0, { 0: "OFPPR_ADD",
+                                                 1: "OFPPR_DELETE",
+                                                 2: "OFPPR_MODIFY"}),
+                    XBitField("pad", 0, 56),
+                    PacketField("desc", OFPPort(), OFPPort) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTPacketOut(_ofp_header):
+    name = "OFPT_PACKET_OUT"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 13, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
+                    IntEnumField("in_port", "CONTROLLER", ofp_port_no),
+                    FieldLenField("actions_len", None, fmt="H", length_of="actions"),
+                    XBitField("pad", 0, 48),
+                    ActionPacketListField("actions", [], Packet,
+                                          length_from=lambda pkt:pkt.actions_len),
+                    PacketField("data", "", Ether) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTFlowMod(_ofp_header):
+    name = "OFPT_FLOW_MOD"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 14, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    LongField("cookie", 0),
+                    LongField("cookie_mask", 0),
+                    ByteEnumField("table_id", 0, ofp_table),
+                    ByteEnumField("cmd", 0, { 0: "OFPFC_ADD",
+                                              1: "OFPFC_MODIFY",
+                                              2: "OFPFC_MODIFY_STRICT",
+                                              3: "OFPFC_DELETE",
+                                              4: "OFPFC_DELETE_STRICT" }),
+                    ShortField("idle_timeout", 0),
+                    ShortField("hard_timeout", 0),
+                    ShortField("priority", 0),
+                    IntEnumField("buffer_id", "NO_BUFFER", ofp_buffer),
+                    IntEnumField("out_port", "ANY", ofp_port_no),
+                    IntEnumField("out_group", "ANY", ofp_group),
+                    FlagsField("flags", 0, 16, [ "SEND_FLOW_REM",
+                                                 "CHECK_OVERLAP",
+                                                 "RESET_COUNTS",
+                                                 "NO_PKT_COUNTS",
+                                                 "NO_BYT_COUNTS" ]),
+                    XShortField("pad", 0),
+                    MatchField("match"),
+                    InstructionPacketListField("instructions", [], Packet,
+                                               length_from=lambda pkt:pkt.len-48-(pkt.match.length+(8-pkt.match.length%8)%8)) ]
+                                               # include match padding to match.length
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTGroupMod(_ofp_header):
+    name = "OFPT_GROUP_MOD"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 15, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("cmd", 0, { 0: "OFPGC_ADD",
+                                               1: "OFPGC_MODIFY",
+                                               2: "OFPGC_DELETE" }),
+                    ByteEnumField("group_type", 0, { 0: "OFPGT_ALL",
+                                                     1: "OFPGT_SELECT",
+                                                     2: "OFPGT_INDIRECT",
+                                                     3: "OFPGT_FF" }),
+                    XByteField("pad", 0),
+                    IntEnumField("group_id", 0, ofp_group),
+                    BucketPacketListField("buckets", [], Packet,
+                                          length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTPortMod(_ofp_header):
+    name = "OFPT_PORT_MOD"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 16, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("port_no", 0, ofp_port_no),
+                    XIntField("pad1", 0),
+                    MACField("hw_addr", "0"),
+                    XShortField("pad2", 0),
+                    FlagsField("config", 0, 32, ofp_port_config),
+                    FlagsField("mask", 0, 32, ofp_port_config),
+                    FlagsField("advertise", 0, 32, ofp_port_features),
+                    XIntField("pad3", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTTableMod(_ofp_header):
+    name = "OFPT_TABLE_MOD"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 17, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ByteEnumField("table_id", 0, ofp_table),
+                    X3BytesField("pad", 0),
+                    IntEnumField("config", 0, { 3: "OFPTC_DEPRECATED_MASK"}) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+#####################################################
+################## OFPT_MULTIPART ###################
+#####################################################
+
+ofp_multipart_types = {     0: "OFPMP_DESC",
+                            1: "OFPMP_FLOW",
+                            2: "OFPMP_AGGREGATE",
+                            3: "OFPMP_TABLE",
+                            4: "OFPMP_PORT_STATS",
+                            5: "OFPMP_QUEUE",
+                            6: "OFPMP_GROUP",
+                            7: "OFPMP_GROUP_DESC",
+                            8: "OFPMP_GROUP_FEATURES",
+                            9: "OFPMP_METER",
+                           10: "OFPMP_METER_CONFIG",
+                           11: "OFPMP_METER_FEATURES",
+                           12: "OFPMP_TABLE_FEATURES",
+                           13: "OFPMP_PORT_DESC",
+                        65535: "OFPST_VENDOR" }
+
+ofpmp_request_flags = [ "REQ_MORE" ]
+
+ofpmp_reply_flags = [ "REPLY_MORE" ]
+
+class OFPMPRequestDesc(_ofp_header):
+    name = "OFPMP_REQUEST_DESC"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 0, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMPReplyDesc(_ofp_header):
+    name = "OFPMP_REPLY_DESC"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 0, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad", 0),
+                    StrFixedLenField("mfr_desc", "", 256),
+                    StrFixedLenField("hw_desc", "", 256),
+                    StrFixedLenField("sw_desc", "", 256),
+                    StrFixedLenField("serial_num", "", 32),
+                    StrFixedLenField("dp_desc", "", 256) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestFlow(_ofp_header):
+    name = "OFPMP_REQUEST_FLOW"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 1, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    ByteEnumField("table_id", "ALL", ofp_table),
+                    X3BytesField("pad2", 0),
+                    IntEnumField("out_port", "ANY", ofp_port_no),
+                    IntEnumField("out_group", "ANY", ofp_group),
+                    IntField("pad3", 0),
+                    LongField("cookie", 0),
+                    LongField("cookie_mask", 0),
+                    MatchField("match") ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPFlowStats(Packet):
+    def post_build(self, p, pay):
+        if self.length is None:
+            l = len(p)+len(pay)
+            p = struct.pack("!H", l) + p[2:]
+        return p + pay
+    name = "OFP_FLOW_STATS"
+    fields_desc = [ ShortField("length", None),
+                    ByteEnumField("table_id", 0, ofp_table),
+                    XByteField("pad1", 0),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0),
+                    ShortField("priority", 0),
+                    ShortField("idle_timeout", 0),
+                    ShortField("hard_timeout", 0),
+                    FlagsField("flags", 0, 16, [ "SEND_FLOW_REM",
+                                                 "CHECK_OVERLAP",
+                                                 "RESET_COUNTS",
+                                                 "NO_PKT_COUNTS",
+                                                 "NO_BYT_COUNTS" ]),
+                    IntField("pad2", 0),
+                    LongField("cookie", 0),
+                    LongField("packet_count", 0),
+                    LongField("byte_count", 0),
+                    MatchField("match"),
+                    InstructionPacketListField("instructions", [], Packet,
+                                               length_from=lambda pkt:pkt.length-56-pkt.match.length) ]
+
+class FlowStatsPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_flow_stats_length(s):
+        return struct.unpack("!H", s[:2])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = FlowStatsPacketListField._get_flow_stats_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPFlowStats(current)
+            lst.append(p)
+
+        return remain, lst
+
+class OFPMPReplyFlow(_ofp_header):
+    name = "OFPMP_REPLY_FLOW"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 1, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    FlowStatsPacketListField("flow_stats", [], Packet,
+                                             length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestAggregate(_ofp_header):
+    name = "OFPMP_REQUEST_AGGREGATE"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 2, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    ByteEnumField("table_id", "ALL", ofp_table),
+                    X3BytesField("pad2", 0),
+                    IntEnumField("out_port", "ANY", ofp_port_no),
+                    IntEnumField("out_group", "ANY", ofp_group),
+                    IntField("pad3", 0),
+                    LongField("cookie", 0),
+                    LongField("cookie_mask", 0),
+                    MatchField("match") ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMPReplyAggregate(_ofp_header):
+    name = "OFPMP_REPLY_AGGREGATE"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 2, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    LongField("packet_count", 0),
+                    LongField("byte_count", 0),
+                    IntField("flow_count", 0),
+                    XIntField("pad2", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestTable(_ofp_header):
+    name = "OFPMP_REQUEST_TABLE"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 3, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTableStats(Packet):
+    def extract_padding(self, s):
+        return "", s
+    name = "OFP_TABLE_STATS"
+    fields_desc = [ ByteEnumField("table_id", 0, ofp_table),
+                    X3BytesField("pad1", 0),
+                    IntField("active_count", 0),
+                    LongField("lookup_count", 0),
+                    LongField("matched_count", 0) ]
+
+class OFPMPReplyTable(_ofp_header):
+    name = "OFPMP_REPLY_TABLE"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 3, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    PacketListField("table_stats", None, OFPTableStats,
+                                    length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestPortStats(_ofp_header):
+    name = "OFPMP_REQUEST_PORT_STATS"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 4, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    IntEnumField("port_no", "ANY", ofp_port_no),
+                    XIntField("pad", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPPortStats(Packet):
+    def extract_padding(self, s):
+        return "", s
+    name = "OFP_PORT_STATS"
+    fields_desc = [ IntEnumField("port_no", 0, ofp_port_no),
+                    XIntField("pad", 0),
+                    LongField("rx_packets", 0),
+                    LongField("tx_packets", 0),
+                    LongField("rx_bytes", 0),
+                    LongField("tx_bytes", 0),
+                    LongField("rx_dropped", 0),
+                    LongField("tx_dropped", 0),
+                    LongField("rx_errors", 0),
+                    LongField("tx_errors", 0),
+                    LongField("rx_frame_err", 0),
+                    LongField("rx_over_err", 0),
+                    LongField("rx_crc_err", 0),
+                    LongField("collisions", 0),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0) ]
+
+class OFPMPReplyPortStats(_ofp_header):
+    name = "OFPMP_REPLY_PORT_STATS"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 4, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    PacketListField("port_stats", None, OFPPortStats,
+                                    length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestQueue(_ofp_header):
+    name = "OFPMP_REQUEST_QUEUE"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 5, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    IntEnumField("port_no", "ANY", ofp_port_no),
+                    IntEnumField("queue_id", "ALL", ofp_queue) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPQueueStats(Packet):
+    def extract_padding(self, s):
+        return "", s
+    name = "OFP_QUEUE_STATS"
+    fields_desc = [ IntEnumField("port_no", 0, ofp_port_no),
+                    IntEnumField("queue_id", 0, ofp_queue),
+                    LongField("tx_bytes", 0),
+                    LongField("tx_packets", 0),
+                    LongField("tx_errors", 0),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0) ]
+
+class OFPMPReplyQueue(_ofp_header):
+    name = "OFPMP_REPLY_QUEUE"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 5, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    PacketListField("queue_stats", None, OFPQueueStats,
+                            length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestGroup(_ofp_header):
+    name = "OFPMP_REQUEST_GROUP"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 6, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    IntEnumField("group_id", "ANY", ofp_group),
+                    XIntField("pad2", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPBucketStats(Packet):
+    def extract_padding(self, s):
+        return "", s
+    name = "OFP_BUCKET_STATS"
+    fields_desc = [ LongField("packet_count", 0),
+                    LongField("byte_count", 0) ]
+
+class OFPGroupStats(Packet):
+    def post_build(self, p, pay):
+        if self.length is None:
+            l = len(p)+len(pay)
+            p = struct.pack("!H", l) + p[2:]
+        return p + pay
+    name = "OFP_GROUP_STATS"
+    fields_desc = [ ShortField("length", None),
+                    XShortField("pad1", 0),
+                    IntEnumField("group_id", 0, ofp_group),
+                    IntField("ref_count", 0),
+                    IntField("pad2", 0),
+                    LongField("packet_count", 0),
+                    LongField("byte_count", 0),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0),
+                    PacketListField("bucket_stats", None, OFPBucketStats,
+                                    length_from=lambda pkt:pkt.length-40) ]
+
+class GroupStatsPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_group_stats_length(s):
+        return struct.unpack("!H", s[:2])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = GroupStatsPacketListField._get_group_stats_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPGroupStats(current)
+            lst.append(p)
+
+        return remain, lst
+
+class OFPMPReplyGroup(_ofp_header):
+    name = "OFPMP_REPLY_GROUP"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 6, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    GroupStatsPacketListField("group_stats", [], Packet,
+                                              length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestGroupDesc(_ofp_header):
+    name = "OFPMP_REQUEST_GROUP_DESC"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 7, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPGroupDesc(Packet):
+    def post_build(self, p, pay):
+        if self.length is None:
+            l = len(p)+len(pay)
+            p = struct.pack("!H", l) + p[2:]
+        return p + pay
+    name = "OFP_GROUP_DESC"
+    fields_desc = [ ShortField("length", None),
+                    ByteEnumField("type", 0, { 0: "OFPGT_ALL",
+                                               1: "OFPGT_SELECT",
+                                               2: "OFPGT_INDIRECT",
+                                               3: "OFPGT_FF" }),
+                    XByteField("pad", 0),
+                    IntEnumField("group_id", 0, ofp_group),
+                    BucketPacketListField("buckets", None, Packet,
+                                          length_from=lambda pkt:pkt.length-8) ]
+
+class GroupDescPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_group_desc_length(s):
+        return struct.unpack("!H", s[:2])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = GroupsDescPacketListField._get_group_desc_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPGroupDesc(current)
+            lst.append(p)
+
+        return remain, lst
+
+
+class OFPMPReplyGroupDesc(_ofp_header):
+    name = "OFPMP_REPLY_GROUP_DESC"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 7, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    GroupDescPacketListField("group_descs", [], Packet,
+                                             length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+                    
+class OFPMPRequestGroupFeatures(_ofp_header):
+    name = "OFPMP_REQUEST_GROUP_FEATURES"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 8, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+ofp_action_types_flags = ofp_action_types.values()[:-1]  # no ofpat_experimenter flag
+class OFPMPReplyGroupFeatures(_ofp_header):
+    name = "OFPMP_REPLY_GROUP_FEATURES"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 8, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    FlagsField("types", 0, 32, [ "ALL",
+                                                 "SELECT",
+                                                 "INDIRECT",
+                                                 "FF" ]),
+                    FlagsField("capabilities", 0, 32, [ "SELECT_WEIGHT",
+                                                        "SELECT_LIVENESS",
+                                                        "CHAINING",
+                                                        "CHAINING_CHECKS" ]),
+                    IntField("max_group_all", 0),
+                    IntField("max_group_select", 0),
+                    IntField("max_group_indirect", 0),
+                    IntField("max_group_ff", 0),
+                    # no ofpat_experimenter flag
+                    FlagsField("actions_all", 0, 32, ofp_action_types_flags),
+                    FlagsField("actions_select", 0, 32, ofp_action_types_flags),
+                    FlagsField("actions_indirect", 0, 32, ofp_action_types_flags),
+                    FlagsField("actions_ff", 0, 32, ofp_action_types_flags) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestMeter(_ofp_header):
+    name = "OFPMP_REQUEST_METER"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 9, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    IntEnumField("meter_id", "ALL", ofp_meter),
+                    XIntField("pad2", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMeterBandStats(Packet):
+    def extract_padding(self, s):
+        return "", s
+    name = "OFP_METER_BAND_STATS"
+    fields_desc = [ LongField("packet_band_count", 0),
+                    LongField("byte_band_count", 0) ]
+
+class OFPMeterStats(Packet):
+    def post_build(self, p, pay):
+        if self.len is None:
+            l = len(p)+len(pay)
+            p = p[:4] + struct.pack("!H", l) + p[6:]
+        return p + pay
+    name = "OFP_GROUP_STATS"
+    fields_desc = [ IntEnumField("meter_id", 1, ofp_meter),
+                    ShortField("len", None),
+                    XBitField("pad", 0, 48),
+                    IntField("flow_count", 0),
+                    LongField("packet_in_count", 0),
+                    LongField("byte_in_count", 0),
+                    IntField("duration_sec", 0),
+                    IntField("duration_nsec", 0),
+                    PacketListField("band_stats", None, OFPMeterBandStats,
+                                    length_from=lambda pkt:pkt.len-40) ]
+
+class MeterStatsPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_meter_stats_length(s):
+        return struct.unpack("!H", s[4:6])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        l = 0
+        ret = ""
+        remain = s
+
+        while remain:
+            l = MeterStatsPacketListField._get_meter_stats_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPMeterStats(current)
+            lst.append(p)
+
+        return remain + ret, lst
+
+class OFPMPReplyMeter(_ofp_header):
+    name = "OFPMP_REPLY_METER"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 9, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    MeterStatsPacketListField("meter_stats", [], Packet,
+                                              length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestMeterConfig(_ofp_header):
+    name = "OFPMP_REQUEST_METER_CONFIG"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 10, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    IntEnumField("meter_id", "ALL", ofp_meter),
+                    XIntField("pad2", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMeterConfig(Packet):
+    def post_build(self, p, pay):
+        if self.length is None:
+            l = len(p)+len(pay)
+            p = struct.pack("!H", l) + p[2:]
+        return p + pay
+    name = "OFP_METER_CONFIG"
+    fields_desc = [ ShortField("length", None),
+                    FlagsField("flags", 0, 16, [ "KBPS",
+                                                 "PKTPS",
+                                                 "BURST",
+                                                 "STATS" ]),
+                    IntEnumField("meter_id", 1, ofp_meter),
+                    MeterBandPacketListField("bands", [], Packet,
+                                             length_from=lambda pkt:pkt.len-8) ]
+
+class MeterConfigPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_meter_config_length(s):
+        return struct.unpack("!H", s[:2])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = MeterConfigPacketListField._get_meter_config_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPMeterConfig(current)
+            lst.append(p)
+
+        return remain, lst
+
+class OFPMPReplyMeterConfig(_ofp_header):
+    name = "OFPMP_REPLY_METER_CONFIG"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 10, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    MeterConfigPacketListField("meter_configs", [], Packet,
+                                               length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestMeterFeatures(_ofp_header):
+    name = "OFPMP_REQUEST_METER_FEATURES"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 11, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMPReplyMeterFeatures(_ofp_header):
+    name = "OFPMP_REPLY_METER_FEATURES"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 11, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    IntField("max_meter", 0),
+                    FlagsField("band_types", 0, 32, [ "DROP",
+                                                      "DSCP_REMARK",
+                                                      "EXPERIMENTER" ]),
+                    FlagsField("capabilities", 0, 32, [ "KPBS",
+                                                        "PKTPS",
+                                                        "BURST",
+                                                        "STATS" ]),
+                    ByteField("max_bands", 0),
+                    ByteField("max_color", 0),
+                    XShortField("pad2", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+####### table features for multipart messages #######
+
+class _ofp_table_features_prop_header(Packet):
+    name = "Dummy OpenFlow Table Features Properties Header"
+
+    def post_build(self, p, pay):
+        l = self.length
+        if l is None:
+            l = len(p)+len(pay)
+            p = p[:2] + struct.pack("!H", l) + p[4:]
+        # every message will be padded correctly
+        zero_bytes = (8 - l%8) % 8
+        p += "\x00" * zero_bytes
+        return p + pay
+
+    def extract_padding(self, s):
+        l = self.length
+        zero_bytes = (8 - l%8) % 8
+        return "", s
+
+
+ofp_table_features_prop_types = {     0: "OFPTFPT_INSTRUCTIONS",
+                                      1: "OFPTFPT_INSTRUCTIONS_MISS",
+                                      2: "OFPTFPT_NEXT_TABLES",
+                                      3: "OFPTFPT_NEXT_TABLES_MISS",
+                                      4: "OFPTFPT_WRITE_ACTIONS",
+                                      5: "OFPTFPT_WRITE_ACTIONS_MISS",
+                                      6: "OFPTFPT_APPLY_ACTIONS",
+                                      7: "OFPTFPT_APPLY_ACTIONS_MISS",
+                                      8: "OFPTFPT_MATCH",
+                                     10: "OFPTFPT_WILDCARDS",
+                                     12: "OFPTFPT_WRITE_SETFIELD",
+                                     13: "OFPTFPT_WRITE_SETFIELD_MISS",
+                                     14: "OFPTFPT_APPLY_SETFIELD",
+                                     15: "OFPTFPT_APPLY_SETFIELD_MISS",
+                                  65534: "OFPTFPT_EXPERIMENTER",
+                                  65535: "OFPTFPT_EXPERIMENTER_MISS" }
+
+class OFPTFPTInstructions(_ofp_table_features_prop_header):
+    name = "OFPTFPT_INSTRUCTIONS"
+    fields_desc = [ ShortField("type", 0),
+                    ShortField("length", None),
+                    InstructionIDPacketListField("instruction_ids", [], Packet,
+                                                 length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTInstructionsMiss(_ofp_table_features_prop_header):
+    name = "OFPTFPT_INSTRUCTIONS_MISS"
+    fields_desc = [ ShortField("type", 1),
+                    ShortField("length", None),
+                    InstructionIDPacketListField("instruction_ids", [], Packet,
+                                                 length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTableID(Packet):
+    def extract_padding(self, s):
+        return "", s
+    name = "OFP_TABLE_ID"
+    fields_desc = [ ByteEnumField("table_id", 0, ofp_table) ]
+
+class OFPTFPTNextTables(_ofp_table_features_prop_header):
+    name = "OFPTFPT_NEXT_TABLES"
+    fields_desc = [ ShortField("type", 2),
+                    ShortField("length", None),
+                    PacketListField("next_table_ids", None, OFPTableID,
+                                    length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTNextTablesMiss(_ofp_table_features_prop_header):
+    name = "OFPTFPT_NEXT_TABLES_MISS"
+    fields_desc = [ ShortField("type", 3),
+                    ShortField("length", None),
+                    PacketListField("next_table_ids", None, OFPTableID,
+                                    length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTWriteActions(_ofp_table_features_prop_header):
+    name = "OFPTFPT_WRITE_ACTIONS"
+    fields_desc = [ ShortField("type", 4),
+                    ShortField("length", None),
+                    ActionIDPacketListField("action_ids", [], Packet,
+                                            length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTWriteActionsMiss(_ofp_table_features_prop_header):
+    name = "OFPTFPT_WRITE_ACTIONS_MISS"
+    fields_desc = [ ShortField("type", 5),
+                    ShortField("length", None),
+                    ActionIDPacketListField("action_ids", [], Packet,
+                                            length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTApplyActions(_ofp_table_features_prop_header):
+    name = "OFPTFPT_APPLY_ACTIONS"
+    fields_desc = [ ShortField("type", 6),
+                    ShortField("length", None),
+                    ActionIDPacketListField("action_ids", [], Packet,
+                                            length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTApplyActionsMiss(_ofp_table_features_prop_header):
+    name = "OFPTFPT_APPLY_ACTIONS_MISS"
+    fields_desc = [ ShortField("type", 7),
+                    ShortField("length", None),
+                    ActionIDPacketListField("action_ids", [], Packet,
+                                            length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTMatch(_ofp_table_features_prop_header):
+    name = "OFPTFPT_MATCH"
+    fields_desc = [ ShortField("type", 8),
+                    ShortField("length", None),
+                    OXMIDPacketListField("oxm_ids", [], Packet,
+                                         length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTWildcards(_ofp_table_features_prop_header):
+    name = "OFPTFPT_WILDCARDS"
+    fields_desc = [ ShortField("type", 10),
+                    ShortField("length", None),
+                    OXMIDPacketListField("oxm_ids", [], Packet,
+                                         length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTWriteSetField(_ofp_table_features_prop_header):
+    name = "OFPTFPT_WRITE_SETFIELD"
+    fields_desc = [ ShortField("type", 12),
+                    ShortField("length", None),
+                    OXMIDPacketListField("oxm_ids", [], Packet,
+                                         length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTWriteSetFieldMiss(_ofp_table_features_prop_header):
+    name = "OFPTFPT_WRITE_SETFIELD_MISS"
+    fields_desc = [ ShortField("type", 13),
+                    ShortField("length", None),
+                    OXMIDPacketListField("oxm_ids", [], Packet,
+                                         length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTApplySetField(_ofp_table_features_prop_header):
+    name = "OFPTFPT_APPLY_SETFIELD"
+    fields_desc = [ ShortField("type", 14),
+                    ShortField("length", None),
+                    OXMIDPacketListField("oxm_ids", [], Packet,
+                                         length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTApplySetFieldMiss(_ofp_table_features_prop_header):
+    name = "OFPTFPT_APPLY_SETFIELD_MISS"
+    fields_desc = [ ShortField("type", 15),
+                    ShortField("length", None),
+                    OXMIDPacketListField("oxm_ids", [], Packet,
+                                         length_from=lambda pkt:pkt.length-4) ]
+
+class OFPTFPTExperimenter(_ofp_table_features_prop_header):
+    name = "OFPTFPT_EXPERIMENTER"
+    fields_desc = [ ShortField("type", 65534),
+                    ShortField("length", None),
+                    IntField("experimenter", 0),
+                    IntField("exp_type", 0),
+                    PacketField("experimenter_data", None, Raw) ]
+
+class OFPTFPTExperimenterMiss(_ofp_table_features_prop_header):
+    name = "OFPTFPT_EXPERIMENTER_MISS"
+    fields_desc = [ ShortField("type", 65535),
+                    ShortField("length", None),
+                    IntField("experimenter", 0),
+                    IntField("exp_type", 0),
+                    PacketField("experimenter_data", None, Raw) ]
+
+ofp_table_features_prop_cls = {     0: OFPTFPTInstructions,
+                                    1: OFPTFPTInstructionsMiss,
+                                    2: OFPTFPTNextTables,
+                                    3: OFPTFPTNextTablesMiss,
+                                    4: OFPTFPTWriteActions,
+                                    5: OFPTFPTWriteActionsMiss,
+                                    6: OFPTFPTApplyActions,
+                                    7: OFPTFPTApplyActionsMiss,
+                                    8: OFPTFPTMatch,
+                                   10: OFPTFPTWildcards,
+                                   12: OFPTFPTWriteSetField,
+                                   13: OFPTFPTWriteSetFieldMiss,
+                                   14: OFPTFPTApplySetField,
+                                   15: OFPTFPTApplySetFieldMiss,
+                                65534: OFPTFPTExperimenter,
+                                65535: OFPTFPTExperimenterMiss }
+
+class TableFeaturesPropPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_table_features_prop_length(s):
+        return struct.unpack("!H", s[2:4])[0]
+
+    def m2i(self, pkt, s):
+        t = struct.unpack("!H", s[:2])[0]
+        return ofp_table_features_prop_cls.get(t, Raw)(s)
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+    
+        while remain and len(remain) >= 4:
+            l = TableFeaturesPropPacketListField._get_table_features_prop_length(remain)
+            # add padding !
+            lpad = l + (8 - l%8)%8
+            if l < 4 or len(remain) < lpad:
+            # no zero length nor incoherent length
+                break
+            current = remain[:lpad]
+            remain = remain[lpad:]
+            p = self.m2i(pkt, current)
+            lst.append(p)
+
+        return remain, lst
+
+class OFPTableFeatures(Packet):
+    def post_build(self, p, pay):
+        if self.length is None:
+            l = len(p)+len(pay)
+            p = struct.pack("!H", l) + p[2:]
+        return p + pay
+    name = "OFP_TABLE_FEATURES"
+    fields_desc = [ ShortField("length", None),
+                    ByteEnumField("table_id", 0, ofp_table),
+                    XBitField("pad", 0, 40),
+                    StrFixedLenField("table_name", "", 32),
+                    LongField("metadata_match", 0),
+                    LongField("metadata_write", 0),
+                    IntEnumField("config", 0, { 0: "OFPTC_NO_MASK",
+                                                3: "OFPTC_DEPRECATED_MASK" }),
+                    IntField("max_entries", 0),
+                    TableFeaturesPropPacketListField("properties", [], Packet,
+                                                     length_from=lambda pkt:pkt.length-64) ]
+
+class TableFeaturesPacketListField(PacketListField):
+
+    @staticmethod
+    def _get_table_features_length(s):
+        return struct.unpack("!H", s[:2])[0]
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            l = TableFeaturesPacketListField._get_table_features_length(remain)
+            current = remain[:l]
+            remain = remain[l:]
+            p = OFPTableFeatures(current)
+            lst.append(p)
+
+        return remain, lst
+
+class OFPMPRequestTableFeatures(_ofp_header):
+    name = "OFPMP_REQUEST_TABLE_FEATURES"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 12, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    TableFeaturesPacketListField("table_features", [], Packet,
+                                                 length_from=lambda pkt:pkt.len-16) ] 
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMPReplyTableFeatures(_ofp_header):
+    name = "OFPMP_REPLY_TABLE_FEATURES"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 12, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    TableFeaturesPacketListField("table_features", [], Packet,
+                                                 length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+############### end of table features ###############
+
+class OFPMPRequestPortDesc(_ofp_header):
+    name = "OFPMP_REQUEST_PORT_DESC"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 13, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    IntEnumField("port_no", 0, ofp_port_no),
+                    XIntField("pad", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMPReplyPortDesc(_ofp_header):
+    name = "OFPMP_REPLY_PORT_DESC"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 13, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    PacketListField("ports", None, OFPPort,
+                                    length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPMPRequestExperimenter(_ofp_header):
+    name = "OFPST_REQUEST_EXPERIMENTER"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 18, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 65535, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_request_flags),
+                    XIntField("pad1", 0),
+                    IntField("experimenter", 0),
+                    IntField("exp_type", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPMPReplyExperimenter(_ofp_header):
+    name = "OFPST_REPLY_EXPERIMENTER"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 19, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("mp_type", 65535, ofp_multipart_types),
+                    FlagsField("flags", 0, 16, ofpmp_reply_flags),
+                    XIntField("pad1", 0),
+                    IntField("experimenter", 0),
+                    IntField("exp_type", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+# ofp_multipart_request/reply_cls allows generic method OpenFlow()
+# to choose the right class for dissection
+ofp_multipart_request_cls = {     0: OFPMPRequestDesc,
+                                  1: OFPMPRequestFlow,
+                                  2: OFPMPRequestAggregate,
+                                  3: OFPMPRequestTable,
+                                  4: OFPMPRequestPortStats,
+                                  5: OFPMPRequestQueue,
+                                  6: OFPMPRequestGroup,
+                                  7: OFPMPRequestGroupDesc,
+                                  8: OFPMPRequestGroupFeatures,
+                                  9: OFPMPRequestMeter,
+                                 10: OFPMPRequestMeterConfig,
+                                 11: OFPMPRequestMeterFeatures,
+                                 12: OFPMPRequestTableFeatures,
+                                 13: OFPMPRequestPortDesc,
+                              65535: OFPMPRequestExperimenter }
+
+ofp_multipart_reply_cls = {     0: OFPMPReplyDesc,
+                                1: OFPMPReplyFlow,
+                                2: OFPMPReplyAggregate,
+                                3: OFPMPReplyTable,
+                                4: OFPMPReplyPortStats,
+                                5: OFPMPReplyQueue,
+                                6: OFPMPReplyGroup,
+                                7: OFPMPReplyGroupDesc,
+                                8: OFPMPReplyGroupFeatures,
+                                9: OFPMPReplyMeter,
+                               10: OFPMPReplyMeterConfig,
+                               11: OFPMPReplyMeterFeatures,
+                               12: OFPMPReplyTableFeatures,
+                               13: OFPMPReplyPortDesc,
+                            65535: OFPMPReplyExperimenter }
+
+############## end of OFPT_MULTIPART ################
+
+class OFPTBarrierRequest(_ofp_header):
+    name = "OFPT_BARRIER_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 20, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTBarrierReply(_ofp_header):
+    name = "OFPT_BARRIER_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 21, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTQueueGetConfigRequest(_ofp_header):
+    name = "OFPT_QUEUE_GET_CONFIG_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 22, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("port_no", "ANY", ofp_port_no),
+                    XIntField("pad", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTQueueGetConfigReply(_ofp_header):
+    name = "OFPT_QUEUE_GET_CONFIG_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 23, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("port", 0, ofp_port_no),
+                    XIntField("pad", 0),
+                    QueuePacketListField("queues", [], Packet,
+                                         length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTRoleRequest(_ofp_header):
+    name = "OFPT_ROLE_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 24, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("role", 0, { 0: "OFPCR_ROLE_NOCHANGE",
+                                              1: "OFPCR_ROLE_EQUAL",
+                                              2: "OFPCR_ROLE_MASTER",
+                                              3: "OFPCR_ROLE_SLAVE" }),
+                    XIntField("pad", 0),
+                    LongField("generation_id", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTRoleReply(_ofp_header):
+    name = "OFPT_ROLE_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 25, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    IntEnumField("role", 0, { 0: "OFPCR_ROLE_NOCHANGE",
+                                              1: "OFPCR_ROLE_EQUAL",
+                                              2: "OFPCR_ROLE_MASTER",
+                                              3: "OFPCR_ROLE_SLAVE" }),
+                    XIntField("pad", 0),
+                    LongField("generation_id", 0) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTGetAsyncRequest(_ofp_header):
+    name = "OFPT_GET_ASYNC_REQUEST"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 26, ofp_type),
+                    ShortField("len", 8),
+                    IntField("xid", 0) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+ofp_packet_in_reason = [ "NO_MATCH",
+                         "ACTION",
+                         "INVALID_TTL" ]
+
+ofp_port_reason = [ "ADD",
+                    "DELETE",
+                    "MODIFY" ]
+
+ofp_flow_removed_reason = [ "IDLE_TIMEOUT",
+                            "HARD_TIMEOUT",
+                            "DELETE",
+                            "GROUP_DELETE" ]
+
+class OFPTGetAsyncReply(_ofp_header):
+    name = "OFPT_GET_ASYNC_REPLY"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 27, ofp_type),
+                    ShortField("len", 32),
+                    IntField("xid", 0),
+                    FlagsField("packet_in_mask_master", 0, 32, ofp_packet_in_reason),
+                    FlagsField("packet_in_mask_slave", 0, 32, ofp_packet_in_reason),
+                    FlagsField("port_status_mask_master", 0, 32, ofp_port_reason),
+                    FlagsField("port_status_mask_slave", 0, 32, ofp_port_reason),
+                    FlagsField("flow_removed_mask_master", 0, 32, ofp_flow_removed_reason),
+                    FlagsField("flow_removed_mask_slave", 0, 32, ofp_flow_removed_reason) ]
+    overload_fields = {TCP: {"dport": 6653}}
+
+class OFPTSetAsync(_ofp_header):
+    name = "OFPT_SET_ASYNC"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 28, ofp_type),
+                    ShortField("len", 32),
+                    IntField("xid", 0),
+                    FlagsField("packet_in_mask_master", 0, 32, ofp_packet_in_reason),
+                    FlagsField("packet_in_mask_slave", 0, 32, ofp_packet_in_reason),
+                    FlagsField("port_status_mask_master", 0, 32, ofp_port_reason),
+                    FlagsField("port_status_mask_slave", 0, 32, ofp_port_reason),
+                    FlagsField("flow_removed_mask_master", 0, 32, ofp_flow_removed_reason),
+                    FlagsField("flow_removed_mask_slave", 0, 32, ofp_flow_removed_reason) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+class OFPTMeterMod(_ofp_header):
+    name = "OFPT_METER_MOD"
+    fields_desc = [ ByteEnumField("version", 0x04, ofp_version),
+                    ByteEnumField("type", 29, ofp_type),
+                    ShortField("len", None),
+                    IntField("xid", 0),
+                    ShortEnumField("cmd", 0, { 0: "OFPMC_ADD",
+                                               1: "OFPMC_MODIFY",
+                                               2: "OFPMC_DELETE" }),
+                    FlagsField("flags", 0, 16, [ "KBPS",
+                                                 "PKTPS",
+                                                 "BURST",
+                                                 "STATS" ]),
+                    IntEnumField("meter_id", 1, ofp_meter),
+                    MeterBandPacketListField("bands", [], Packet,
+                                             length_from=lambda pkt:pkt.len-16) ]
+    overload_fields = {TCP: {"sport": 6653}}
+
+# ofpt_cls allows generic method OpenFlow() to choose the right class for dissection
+ofpt_cls = {  0: OFPTHello,
+              #1: OFPTError,
+              2: OFPTEchoRequest,
+              3: OFPTEchoReply,
+              4: OFPTExperimenter,
+              5: OFPTFeaturesRequest,
+              6: OFPTFeaturesReply,
+              7: OFPTGetConfigRequest,
+              8: OFPTGetConfigReply,
+              9: OFPTSetConfig,
+             10: OFPTPacketIn,
+             11: OFPTFlowRemoved,
+             12: OFPTPortStatus,
+             13: OFPTPacketOut,
+             14: OFPTFlowMod,
+             15: OFPTGroupMod,
+             16: OFPTPortMod,
+             17: OFPTTableMod,
+             #18: OFPTMultipartRequest,
+             #19: OFPTMultipartReply,
+             20: OFPTBarrierRequest,
+             21: OFPTBarrierReply,
+             22: OFPTQueueGetConfigRequest,
+             23: OFPTQueueGetConfigReply,
+             24: OFPTRoleRequest,
+             25: OFPTRoleReply,
+             26: OFPTGetAsyncRequest,
+             27: OFPTGetAsyncReply,
+             28: OFPTSetAsync,
+             29: OFPTMeterMod }
+
+TCP_guess_payload_class_copy = TCP.guess_payload_class
+
+def OpenFlow(self, payload):
+    if self is None or self.dport == 6653 or self.dport == 6633 or self.sport == 6653 or self.sport == 6653:
+    # port 6653 has been allocated by IANA, port 6633 should no longer be used
+    # OpenFlow function may be called with None self in OFPPacketField
+        of_type = ord(payload[1])
+        if of_type == 1:
+            err_type = ord(payload[9])
+            # err_type is a short int, but last byte is enough
+            if err_type == 255: err_type = 65535
+            return ofp_error_cls[err_type]
+        elif of_type == 16:
+            mp_type = ord(payload[9])
+            if mp_type == 255: mp_type = 65535
+            return ofp_multipart_request_cls[mp_type]
+        elif of_type == 17:
+            mp_type = ord(payload[9])
+            if mp_type == 255: mp_type = 65535
+            return ofp_multipart_reply_cls[mp_type]
+        else:
+            return ofpt_cls[of_type]
+    else:
+        return TCP_guess_payload_class_copy(self, payload)
+
+TCP.guess_payload_class = OpenFlow
diff --git a/scapy/contrib/openflow3.uts b/scapy/contrib/openflow3.uts
new file mode 100755
index 0000000000000000000000000000000000000000..7984fa56aa3ba87faf814cb310c1197f1bbabe55
--- /dev/null
+++ b/scapy/contrib/openflow3.uts
@@ -0,0 +1,83 @@
+% Tests for OpenFlow v1.3 with Scapy
+
++ Usual OFv1.3 messages
+
+= OFPTHello(), hello without version bitmap
+ofm = OFPTHello()
+str(ofm) == '\x04\x00\x00\x08\x00\x00\x00\x00'
+
+= OFPTEchoRequest(), echo request
+ofm = OFPTEchoRequest()
+str(ofm) == '\x04\x02\x00\x08\x00\x00\x00\x00'
+
+= OFPMatch(), check padding
+ofm = OFPMatch(oxm_fields=OFBEthType(eth_type=0x86dd))
+assert(len(str(ofm))%8 == 0)
+str(ofm) == '\x00\x01\x00\x0a\x80\x00\x0a\x02\x86\xdd\x00\x00\x00\x00\x00\x00'
+
+= OpenFlow(), generic method test with OFPTEchoRequest()
+ofm = OFPTEchoRequest()
+s = str(ofm)
+isinstance(OpenFlow(None,s)(s), OFPTEchoRequest)
+
+= OFPTFlowMod(), check codes and defaults values
+ofm = OFPTFlowMod(cmd='OFPFC_DELETE', out_group='ALL', flags='CHECK_OVERLAP+NO_PKT_COUNTS')
+assert(ofm.cmd == 3)
+assert(ofm.out_port == 0xffffffff)
+assert(ofm.out_group == 0xfffffffc)
+ofm.flags == 10
+
+= OFBIPv6ExtHdrHMID(), check creation of last OXM classes
+assert(hasattr(OFBIPv6ExtHdr(), 'ipv6_ext_hdr_flags'))
+OFBIPv6ExtHdrHMID().field == 39
+
++ Complex OFv1.3 messages
+
+= OFPTFlowMod(), complex flow_mod
+mtc = OFPMatch(oxm_fields=OFBVLANVID(vlan_vid=10))
+ist1 = OFPITApplyActions(actions=[OFPATSetField(field=OFBIPv4Src(ipv4_src='192.168.10.41')),OFPATSetField(field=OFBEthSrc(eth_src='1a:d5:cb:4e:3c:64')),OFPATOutput(port='NORMAL')])
+ist2 = OFPITWriteActions(actions=OFPATOutput(port='CONTROLLER'))
+ofm = OFPTFlowMod(table_id=2, match=mtc, instructions=[ist1,ist2])
+hexdump(ofm)
+s = '\x04\x0e\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x01\x00\x0a\x80\x00\x0c\x02\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x04\x00\x38\x00\x00\x00\x00\x00\x19\x00\x10\x80\x00\x16\x04\xc0\xa8\x0a\x29\x00\x00\x00\x00\x00\x19\x00\x10\x80\x00\x08\x06\x1a\xd5\xcb\x4e\x3c\x64\x00\x00\x00\x00\x00\x10\xff\xff\xff\xfa\xff\xff\x00\x00\x00\x00\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\xff\xff\xff\xfd\xff\xff\x00\x00\x00\x00\x00\x00'
+str(ofm) == s
+
+= OFPETBadRequest() containing a flow_mod with wrong table_id
+flowmod = OFPTFlowMod(instructions=OFPITGotoTable(table_id=0))
+ofm = OFPETBadRequest(errcode='OFPBRC_BAD_TABLE_ID', data=str(flowmod))
+hexdump(ofm)
+s = '\x04\x01\x00L\x00\x00\x00\x00\x00\x01\x00\t\x04\x0e\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x01\x00\x04\x00\x00\x00\x00\x00\x01\x00\x08\x00\x00\x00\x00'
+str(ofm) == s
+
+= OFPTPacketIn() containing an Ethernet frame
+ofm = OFPTPacketIn(data=Ether()/IP()/ICMP())
+p = OFPTPacketIn(str(ofm))
+dat = p.data
+assert(isinstance(dat, Ether))
+assert(isinstance(dat.payload, IP))
+isinstance(dat.payload.payload, ICMP)
+
++ Layer bindings
+
+= TCP()/OFPMPRequestDesc(), check default sport
+p = TCP()/OFPMPRequestDesc()
+p[TCP].sport == 6653
+
+= TCP()/OFPETHelloFailed(), check default dport
+p = TCP()/OFPETHelloFailed()
+p[TCP].dport == 6653
+
+= TCP()/OFPTHello() dissection, check new TCP.guess_payload_class
+o = TCP()/OFPTHello()
+p = TCP(str(o))
+p[TCP].sport == 6653
+isinstance(p[TCP].payload, OFPTHello)
+
+= complete Ether()/IP()/TCP()/OFPTFeaturesRequest()
+ofm = Ether(src='00:11:22:33:44:55',dst='01:23:45:67:89:ab')/IP(src='10.0.0.7',dst='192.168.0.42')/TCP(sport=6633)/OFPTFeaturesRequest(xid=23)
+s = '\x01#Eg\x89\xab\x00\x11"3DU\x08\x00E\x00\x000\x00\x01\x00\x00@\x06\xaf\xee\n\x00\x00\x07\xc0\xa8\x00*\x19\xe9\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\xa6\xa4\x00\x00\x04\x05\x00\x08\x00\x00\x00\x17'
+assert(str(ofm) == s)
+e = Ether(s)
+e.show2()
+of = OFPTFeaturesRequest(e[TCP].load)
+of.xid == 23